Template constructor in a class template - how to explicitly specify template argument for the 2nd parameter?
compile error when tried to explicit specify template
You can explicitly specify the template arguments for your calls to foo
because those member functions foo
have names -- and the template arguments are part of that name.
That doesn't work with constructors because a constructor has no name. You can't (directly) call a constructor. A constructor is of course called when you create an object, but the call is generated code.
Fixing your code, the following would work:
template<class T> class TestTemplate {
public:
//constructor 1
template<class Y> TestTemplate(Y * p) {
cout << "c1" << endl;
}
//constructor 2
template<class Y, class D> TestTemplate(Y * p, D d) {
cout << "c2" << endl;
}
template<class A, class B>
void foo(A a, B b) {
cout << "foo" << endl;
}
};
int main() {
TestTemplate<int> tp(new int());
tp.foo<int*, string>(new int(), "hello");
TestTemplate<int> tp2(new int(),2);
}
You cannot use T
for the class template parameter and the constructor template parameter. But, to answer your question, from [14.5.2p5]:
Because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates.
Therefore, you cannot explicitly specify template arguments for constructor.
You can't explicitly specify the template arguments for a constructor, because the constructor has no name on its own, and so there's no syntax for it.
But, you can ensure that correct template arguments are inferred, by
casting actual arguments, and/or
introducing "artificial" extra arguments just to carry type information, if necessary, and/or
use a factory function.
For example, you can define
template< class Type > struct TypeCarrier{ typedef Type T; };
struct MyClass
{
template< class Type >
MyClass( TypeCarrier< Type > ) { ... }
};
...
MyClass o( TypeCarrier<int>() );
But don't get carried away with such techniques.
Instead, if the apparent need to explicitly specify constructor template arguments pops up, think about whether the design is really sound?
Perhaps you can use some simpler design if you reflect on what it’s for?