2

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?

shoosh
  • 76,898
  • 55
  • 205
  • 325
  • See http://stackoverflow.com/questions/984394/why-not-infer-template-parameter-from-constructor – Nick Jun 26 '11 at 18:15
  • possible duplicate of [\[C++\] When template argument deduction fails](http://stackoverflow.com/questions/5528096/c-when-template-argument-deduction-fails) – bobbymcr Jun 26 '11 at 18:16

3 Answers3

3

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.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

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>
Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
0

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,

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434