std::function von Template Methoden in Template Klassen
-
Hallo zusammen,
ich hab mein Problem mal etwas vereinfacht:
#include <functional> template <typename T> struct ClassA { template <typename U> static T foo(int) { return T(U(47)); } }; template <typename T> struct ClassB { template <typename U> static T foo(float) { return T(U(27)); } }; // ClassC, ClassD, ClassE, ... template <typename T> struct Test { std::function<T(int)> classAFun; std::function<T(float)> classBFun; template <typename U> static Test<T> create() { return Test<T>{ClassA<T>::foo<U>, ClassB<T>::foo<U>}; // error } }; int main() { Test<int> t1{ClassA<int>::foo<double>, ClassB<int>::foo<double>}; // ok Test<int> t2 = Test<int>::create<double>(); }Fehlermeldung (kompiliert mit
g++ -std=c++17 test.cpp, g++ version: 9.3.0):test.cpp: In static member function ‘static Test<T> Test<T>::create()’: test.cpp:28:23: error: expected primary-expression before ‘{’ token 28 | return Test<T>{ClassA<T>::foo<U>, | ^ test.cpp:28:23: error: expected ‘;’ before ‘{’ token 28 | return Test<T>{ClassA<T>::foo<U>, | ^ | ;Warum funktioniert das wenn die Template Variablen explizit angegeben werden (
mainMethode Zeil 35) und warum nicht in dercreateMethode (Zeile 28)?Kennt jemanden eine Lösung für die
createMethode?Danke
-
@klaus sagte in std::function von Template Methoden in Template Klassen:
template <typename U> static Test<T> create() { return Test<T>{ClassA<T>::foo<U>, ClassB<T>::foo<U>}; // error }Hier ist nicht bekannt wie die Klassen
ClassA<T>undClassB<T>aufgebaut sind da diese vom (unbekannten) TypTabhängig sind (ClassA<T>undClassB<T>sind "dependent types"). Du musst daher Member die selbst wieder ein Template sind mit dem Keywordtemplatekennzeichnen, genau so wie du Typ-Member mit dem Keywordtypenamekennzeichnen müsstest:template <typename U> static Test<T> create() { return Test<T>{ClassA<T>::template foo<U>, ClassB<T>::template foo<U>}; // error }
-
BTW: Du hast das Beispiel schonmal gut gekürzt, das sollte wenn man es nicht sofort sehen/fixen kann immer der erste Schritt sein.
Was danach oft hilft ist das ganze einem anderen Compiler zu füttern. Was mit Services wie godbolt.org sehr schön geht.Clang sagt da z.B.:
<source>:28:35: error: use 'template' keyword to treat 'foo' as a dependent template name return Test<T>{ClassA<T>::foo<U>, ^ template <source>:29:35: error: use 'template' keyword to treat 'foo' as a dependent template name ClassB<T>::foo<U>}; // error ^ template
-
Vielen Danke für die schnelle Antwort, Lösung und den Tipp
