Schonmal probiert den ein und selben template Datentypen mit sich selbst zu nutzen? Mach nichts, ich auch nicht ;)
Als erstes Beispiel ein einfacher, nicht rekursiver Datentyp:
template<typename T> struct Test { T x; }; auto func() { Test{0}; } error: class template argument deduction failed: Test{0}; error: no matching function for call to 'Test(int)' note: candidate: 'template<class T> Test(Test<T>)-> Test<T>'
Seit C++17 gibt es Class template argument deduction. Allerdings muss man für User-defined typen auch User-defined deduction guides angeben. Dieser hier ist sehr simpel.
template<typename T> Test(T) -> Test<T>;
Damit compiliert das oben gezeigte Beispiel (ab GCC7).
Und nun zu dem rekursiven Typen. Ob es geklappt hat, lässt sich mit einem static_assert mit std::is_same zeigen.
template<typename T> auto func2(T) { static_assert(std::is_same_v<T, Test<Test<int>> >); } auto func() { func2( Test{Test{0}} ); // Dies ruft den Copy-Konstruktor auf } In instantiation of 'auto func2(T) [with T = Test<int>]': error: static assertion failed
Nein es hat nicht geklappt. Der Grund hierfür ist, dass wir ja eigentlich den Copy-Konstruktor aufgerufen haben.
Mit den deduction guides können wir aber dem Compiler bessere Anweisungen geben.
template<typename T> Test(Test<T>) -> Test<Test<T>>;
Damit compiliert der Code nun.
Vielen Dank an Freundlich aus dem #c++ Chat für die Fragestellung ;)