Class constructor with template type without arguments

It is possible for a normal C ++ function to have template parameters that are not in the argument list:

template<typename T>
T default_construct()
{
    return T();
}

      

and call it with

some_type x = default_construct<some_type>();

      

Although the type I am using is not in the argument list, I can still pass it to the function. Now I want to do this in the constructor of the class:

struct Base;

template<typename T>
Base* allocate()
{
    return new T; //Assume T derives from Base...
}

struct factory {
    template<typename T>
    factory()
        : func(allocate<T>)
    {}

    std::tr1::function<Base*()> func;
};

      

but I can't find a way to provide a parameter to a constructor when I want to build an instance factory

.

Is there a way to do this without turning the class into a templated class, or sending some unused object T

to the constructor?

+2


source to share


3 answers


No, there is no way to do it. A note in 14.8.1/5

the Standard explains why

[Note: Because the explicit template argument list follows the function template name, and since member function templates and constructor member function templates are called without using the function name, there is no way to provide an explicit template argument list for these functional templates. ]



Of course, it doesn't have to be the object T

you are sending. It can be any object that has T

, encoded in its type

template<typename T> struct type2type { };

struct factory {
    template<typename T>
    factory(type2type<T>)
        : func(allocate<T>)
    {}

    std::tr1::function<Base*()> func;
};

factory f((type2type<Foo>()));

      

+9


source


No, you cannot. The use of an unused object of a given type is invoked using an object of the tag type. You can create global types of each type, or use the default constructor every time.



You can hope that if the constructor is inline, the type tag will never be created.

+3


source


The labels and wrang-wrang answers are good. As another possibility, you might consider declaring all of your (non-copies) constructors private or protected, and creating one or more static member function templates factory create<T>()

. Then to define a factory instance instead

factory<SomeType> f;                      // 1 (doesn't compile)

      

You write

factory f(factory::create<SomeType>());   // 2

      

Obviously it's not quite as pretty as (1), but IMHO is a little clearer than using type tags. (The compiler will exclude the copy in practice.)

By the way, is there a reason why you couldn't just make a factory

template template? Then the syntax from (1) will compile. (This would mean, however, that factories of different types cannot be assigned to each other.)

0


source







All Articles