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 (
main
Methode Zeil 35) und warum nicht in dercreate
Methode (Zeile 28)?Kennt jemanden eine Lösung für die
create
Methode?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) TypT
abhängig sind (ClassA<T>
undClassB<T>
sind "dependent types"). Du musst daher Member die selbst wieder ein Template sind mit dem Keywordtemplate
kennzeichnen, genau so wie du Typ-Member mit dem Keywordtypename
kennzeichnen 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