命名构造函数习惯用法和模板?

发布于 2024-10-21 02:09:00 字数 1104 浏览 6 评论 0原文

有没有办法使用 命名构造函数惯用语 “漂亮”时尚的模板?

例如:

#include <vector>
using namespace std;

template< typename T >
class Foo
{
public:
    static Foo Copy(const T& arg)
    {
        Foo ret;
        ret.t_copy = arg;
        return ret;
    }

    static Foo CopyClear(const T& arg)
    {
        Foo ret;
        ret.t_copy = arg;
        ret.t_copy.clear();
        return ret;
    }

private:
    T t_copy;
};


int main( int argc, char** argv )
{
    vector<double> vec;
    vec.push_back(1);

    // #1: won't compile
    Foo< vector<double> > a_foo = Foo::CopyClear( vec );

    // #2: ugly, but works
    Foo< vector<double> > a_foo = Foo< vector<double> >::CopyClear( vec );

    return 0;
}

我想以某种方式使用 #1 的语法。 #2 有效,但让我的 DRY 感觉错误。

编辑:Foo 的新的、更“现实”的版本。

EDIT2:恐怕我没有 C++0x/C++1x :(

Is there a way to use the Named Constructor Idiom with templates in a "pretty" fashion?

For instance:

#include <vector>
using namespace std;

template< typename T >
class Foo
{
public:
    static Foo Copy(const T& arg)
    {
        Foo ret;
        ret.t_copy = arg;
        return ret;
    }

    static Foo CopyClear(const T& arg)
    {
        Foo ret;
        ret.t_copy = arg;
        ret.t_copy.clear();
        return ret;
    }

private:
    T t_copy;
};


int main( int argc, char** argv )
{
    vector<double> vec;
    vec.push_back(1);

    // #1: won't compile
    Foo< vector<double> > a_foo = Foo::CopyClear( vec );

    // #2: ugly, but works
    Foo< vector<double> > a_foo = Foo< vector<double> >::CopyClear( vec );

    return 0;
}

I'd like to use the syntax of #1 somehow. #2 works but rubs my DRY sense the wrong way.

EDIT: New, more "realistic" version of Foo.

EDIT2: No C++0x/C++1x for me I'm afraid :(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

裸钻 2024-10-28 02:09:00

更新的答案

如果我正确理解你的意图,这将达到目的:

template< typename T >
class Foo
{
private:
    friend class FooHelper;
    size_t sz;
};

class FooHelper
{
public:
    template< typename T >
    static Foo<T> Size(const T& arg)
    {
        Foo<T> ret;
        ret.sz = arg.size();
        return ret;
    }

    template< typename T >
    static Foo<T> HalfSize(const T& arg)
    {
        Foo<T> ret;
        ret.sz = arg.size() / 2;
        return ret;
    }
};

然后编译:

int main( int argc, char** argv )
{
    vector<double> vec;
    vec.push_back(1);

    Foo<vector<double>> a_foo = FooHelper::HalfSize( vec );
}

Updated answer

If I understand your intent correctly, this will do the trick:

template< typename T >
class Foo
{
private:
    friend class FooHelper;
    size_t sz;
};

class FooHelper
{
public:
    template< typename T >
    static Foo<T> Size(const T& arg)
    {
        Foo<T> ret;
        ret.sz = arg.size();
        return ret;
    }

    template< typename T >
    static Foo<T> HalfSize(const T& arg)
    {
        Foo<T> ret;
        ret.sz = arg.size() / 2;
        return ret;
    }
};

This then compiles:

int main( int argc, char** argv )
{
    vector<double> vec;
    vec.push_back(1);

    Foo<vector<double>> a_foo = FooHelper::HalfSize( vec );
}
梦情居士 2024-10-28 02:09:00

我不认为存在 DRY 问题,将其视为语言限制。
如果您有一个没有模板的 Foo 类,但您想从静态方法创建一个新对象,则必须执行以下操作:

Foo a_foo = Foo::HalfSize(something);

当然 Foo 重复了两次。

因此,由于这里完整的类名称是 Foo<;矢量<双> >,从 Foo< 获取静态方法是符合逻辑的。矢量<双> >::HalfSize(),因为这是 C++ 的方式。

I don't think there is a DRY problem, think of it as a language restriction.
If you have a Class Foo without template but you want to create a new object from a static method, you'd have to do something like:

Foo a_foo = Foo::HalfSize(something);

and there's of course the Foo repeated twice.

So, since here the full Class name is Foo< vector<double> >, it's logical to get the static method from Foo< vector<double> >::HalfSize(), since that's the C++ way.

请远离我 2024-10-28 02:09:00

除了 @Jon 的答案之外,如果您需要类本身作为模板,请参阅 std::make_pair 及其与 std::pair 的关系。

In addition to @Jon's answer, see std::make_pair and its relationship to std::pair, if you need the class itself to be a template.

枯寂 2024-10-28 02:09:00

这在技术上是可以的,并且可能是对您的最终问题的最简单答案:

    Foo< vector<double> > a_foo = a_foo.CopyClear( vec );

技术上可以,因为CopyClear是一个静态 会员功能。

并且不存在技术问题,例如您可以使用 typedef 代替。或者只是将这些静态成员函数作为函数模板放在命名空间范围内。或者在一些辅助类中,正如有人已经建议的那样。

但即使没有技术问题,设计也不太理想;坦率地说(抱歉),这比毫无意义更糟糕。

例如,在CopyClear中,为什么要复制向量然后丢弃复制结果?您只需要创建一个您的代码知道的类型的空向量。

例如,为什么要引入副作用机制?

副作用是要避免和消除的,而不是引入的。

干杯&呵呵,

This is technically OK and is possibly the simplest answer to your end question:

    Foo< vector<double> > a_foo = a_foo.CopyClear( vec );

It's technically OK because CopyClear is a static member function.

And there is no technical problem, e.g. you could use a typedef instead. Or just put those static member functions at namespace scope, as function templates. Or in some helper class, as someone has already suggested.

But even though there is no technical problem, the design is less than ideal; it is, to put it bluntly (sorry), a bit worse than meaningless.

For example, in CopyClear, why are you copying a vector and then discarding the copy result? You only need to create an empty vector, of the type your code knows.

And for example, why are you introducing side-effect machinery?

Side-effects are to be avoided and removed, not introduced.

Cheers & hth.,

猫烠⑼条掵仅有一顆心 2024-10-28 02:09:00

如果您可以使用 C++0x 功能,auto 关键字将会有所帮助。 Size()HalfSize() 需要是静态方法是否有原因?如果您提供改变 sz 的方法,您可以这样做:

template<class T>
Foo<T> HalfSize(const T& arg)
{
    Foo<T> ret;
    ret.setSz(arg.size() / 2); // or similar
    return ret;
}

然后#1 更容易实现。

If you can use C++0x features, the auto keyword would help. Is there a reason that Size() and HalfSize() need to be static methods? If you provide methods to mutate sz you can do this:

template<class T>
Foo<T> HalfSize(const T& arg)
{
    Foo<T> ret;
    ret.setSz(arg.size() / 2); // or similar
    return ret;
}

and then #1 is a little more attainable.

旧伤还要旧人安 2024-10-28 02:09:00

C++1x 来救援:

auto a_foo = Foo::HalfSize<vector<double>>( vec );

是的,两个结束 >> 被解析为 > C++1x 中的 >

您附近的编译器可能已经可用。

C++1x to the rescue:

auto a_foo = Foo::HalfSize<vector<double>>( vec );

And, yes, the two closing >> are parsed as > > in C++1x.

Probably already available with a compiler near you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文