55

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

Anycorn
  • 50,217
  • 42
  • 167
  • 261

1 Answers1

55

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.

Benjamin Buch
  • 4,752
  • 7
  • 28
  • 51
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 22
    @litb: Do you know if there's any reason they simply don't let you explicitly call T::T()? – Joseph Garvin Jul 16 '11 at 18:06
  • Thanks for this answer. The same workaround can be used to call a templated constructor via `std::vector::emplace_back()` etc. – John Zwinck Aug 21 '17 at 01:54
  • This answer could be improved if you explained what the Standard is talking about. I read it multiple times, and I'm still confused. It seems like you took our understanding it for granted, but not everyone is a Language Lawyer ;) – Keith M Nov 30 '18 at 20:59
  • 1
    @KeithM you can specify what confuses you and then we may surely be able to clarify your understanding of the note. Maybe this is enough: If you use `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. – Johannes Schaub - litb Dec 01 '18 at 17:17
  • 1
    It's just kind of a word salad, there. `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()` 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?) – Keith M Dec 03 '18 at 19:00
  • (Ran out of chars, so double posting) By the way, I thought Constructors/Destructors had names, but the names matched the type names (plus a prefixed ~ for d'tor). Hence why you could do `T t(); t.T();` if you really wanted to (although that would call the c'tor twice). No? – Keith M Dec 03 '18 at 19:02
  • 1
    @KeithM I have added an explanation for the note. – Johannes Schaub - litb Dec 04 '18 at 20:19
  • 1
    @KeithM as for the reason, I don't know, but could guess they didn't find a compelling use case. Maybe you could create a new question for this. – Johannes Schaub - litb Dec 04 '18 at 20:29
  • @Keith: [No](https://eel.is/c++draft/class.ctor#general-1.sentence-2) (the standard wording isn't quite as clear about destructors, but [we can probably agree the same is true for them](https://stackoverflow.com/q/2693199/4386278)) – Asteroids With Wings Oct 30 '20 at 20:22