命名构造函数成语和模板?

时间:2011-03-10 21:50:24

标签: c++ templates constructor

有没有办法以“漂亮”的方式使用Named Constructor Idiom模板?

例如:

#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我害怕:(

6 个答案:

答案 0 :(得分:3)

更新回答

如果我理解你的意图,这将解决问题:

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 );
}

答案 1 :(得分:3)

我认为没有干燥问题,将其视为语言限制。 如果你有一个没有模板的Class Foo,但你想从静态方法创建一个新对象,你必须做类似的事情:

Foo a_foo = Foo::HalfSize(something);

当然,Foo重复了两次。

因此,由于这里的完整类名是Foo< vector<double> >,因此从Foo< vector<double> >::HalfSize()获取静态方法是合乎逻辑的,因为这是C ++方式。

答案 2 :(得分:3)

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

答案 3 :(得分:3)

这在技术上是正常的,可能是您结束问题的最简单答案:

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

技术上确定,因为CopyClearstatic成员函数。

并且没有技术问题,例如你可以改用typedef。或者只是将那些static成员函数放在命名空间范围内,作为函数模板。或者在某些帮助类中,正如有人已经建议的那样。

但即使没有技术问题,设计还不够理想;直言不讳(对不起),比无意义更糟糕。

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

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

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

干杯&amp;第h。,

答案 4 :(得分:2)

如果您可以使用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更容易实现。

答案 5 :(得分:2)

C ++ 1x救援:

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

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

可能已经有了你附近的编译器。