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 ;)