Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named Constructor Idiom and Templates?

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 :(

like image 707
genpfault Avatar asked Mar 10 '11 21:03

genpfault


2 Answers

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 );
}
like image 152
Jon Avatar answered Oct 13 '22 10:10

Jon


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.

like image 32
Emmanuel Valle Avatar answered Oct 13 '22 12:10

Emmanuel Valle