Can you tell me how to invoke template constructor explicitly (in initializer list)? for example:
struct T {
template<class> T();
};
struct U {
U() : t<void>() {} //does not work
T t;
};
thanks
It's not possible. The Standard also has a note on this at 14.8.1/7
[Note: 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. ]
Explanation: This says: Template arguments are passed in angle brackets after a function template name, such as std::make_pair<int, bool>. And constructors don't have a name of their own, but they abuse their class names in various contexts (so U<int>() means: Pass <int> to the class template U, and construct an object by calling the default constructor without arguments). Therefore, one cannot pass template arguments to constructors.
In your case, you are trying to pass template arguments in a member initializer. In that case, there's even more of a problem: It will attempt to parse and interpret t<void> as a base-class type and thinks you want to call the default constructor of a base class. This will fail, of course.
If you can live with it, you can work it around
struct T {
template<class U> T(identity<U>);
};
struct U {
U() : t(identity<void>()) {}
T t;
};
Given identity like it's defined in boost
template<typename T> struct identity { typedef T type; };
Within C++20 you can use std::type_identity as identity type.
T::T<foo>(); and T<foo>::T(); are just short forms of T<foo>::T<foo>();. T<foo> is the actual identity of the constructor (you can even declare it this way), it's just normally implicit in the remaining cases so we don't need to state foo more than once. That said, this doesn't change your point, but the syntax would have to be T<foo>::T<foo><bar>() in order to allow existing code to be unaffected.T(), then T is the name of the struct T, and not the name of the constructor (which doesn't have one). So if you say T<...>() then whatever arguments are passed, are not passed to the constructor, but are tried to be passed to the struct, which is not a template at all.explicit template argument list, function template name, conversion member function templates, constructor member function templates. I understood virtually none of that abstract terminology (sorry, couldn't resist the pun). After reading your new comment and the paragraph again, I might understand (although I still don't know the terminology). I think it's saying that : t<void>() doesn't work because template affixes always come after type names or function names, and t is neither. Is that right? (But why not change the std to allow it?)