Reputation: 78934
I often find the need to use the following pattern:
template<typename T>
class SomeClass : public Base {
SomeClass(const T& t) {...}
...
};
template<typename T>
SomeClass<T>* makeSomeClass(const T& t) {
return new SomeClass<T>(t);
}
And to use it:
Base* = makeSomeClass(123);
This is useful when I don't want to explicitly specify T
because it is a very complex (function types, etc') and the function argument can deduce the type implicitly.
Is there a way to do this without the extra "make" function? Why does template deduction work only in function arguments and not in constructor arguments?
Upvotes: 2
Views: 490
Reputation: 54270
No, there is no way to do this without an extra make function.
The reason it doesn't work with constructors is because it would be ridiculously complicated. Consider this:
template <typename T>
struct Foo
{
Foo(const T& val) { ... }
Foo(const Foo<T>& other) { ... } // Copy constructor
};
Foo<int> x;
What if I then call:
Foo(x);
Does that give me a Foo< Foo<int> >
or am I calling the copy constructor for a Foo<int>
?
It would be ambiguous in too many places, so the extra function is necessary.
Note that you can automate the create of make functions a little by using template templates:
template <template <typename> class TemplateClass, typename Type>
TemplateClass<Type> make(const Type& x)
{
return TemplateClass<Type>(x);
}
Then you can use:
make<SomeClass>(123); // returns a SomeClass<int>
Upvotes: 3
Reputation: 272517
It does work in constructor arguments, if the constructor is itself a template. The difference is that when you use your helper, you're using a function template, where the compiler can deduce the type. Without the helper, you're using a class template, where the compiler would have to somehow deduce the type before calling the (non-template) constructor.
Upvotes: 3
Reputation: 133014
Is there a way without the extra function? No there isn't. Why the deduction works only for functions? Because with functions you actually provide arguments. If it were allowed for classes, then the only way to deduce the template parameters would be in case when a constructor was called for initialization, which makes lots of additional rules and exceptions and complicates things,
Upvotes: 0