[Templates] Wo ist der Fehler?
-
template<typename T, T Factor> struct Reduce { static const T result = 0; }; template<typename T, T Start, template<class U, U Arg> class Expression> struct For { static const T result = For<T, Start - 1, template Expression>::result; }; template<typename T, template<class U, U Arg> class Expression> struct For<T, 0, template Expression> { static const T result = template Expression<T, Start>::result; }; template<typename T, T Arg> struct CallReduce { static const T result = For<T, Arg, Reduce>::result; }; int main() { CallReduce<unsigned, 2u>::result; }C:\src\partial.cpp|12|error: template argument 3 is invalid|
C:\src\partial.cpp|18|error: template argument 3 is invalid|
C:\src\partial.cpp|34|instantiated from here|
C:\src\partial.cpp|27|error:CallReduce<unsigned int, 2u>::result' cannot be initialized by a non-constant expression when being declared| C:\\src\\partial.cpp||In functionint main()':|
C:\src\partial.cpp|34|warning: statement has no effect|
||=== Build finished: 3 errors, 1 warnings ===|ich habe schlicht und einfach keine idee mehr. das weglassen von "template" beim einsetzen als template-argument bringt auch nichts:
C:\src\partial.cpp|12|error: type/value mismatch at argument 3 in template parameter list for
template<class T, T Start, template<class U, U Arg> class Expression> struct For'| C:\\src\\partial.cpp|12|error: expected a template of type \template<class U, U Arg> class Expression', got `template<class U, U Arg> class Expression'|
C:\src\partial.cpp|18|error: type/value mismatch at argument 3 in template parameter list fortemplate<class T, T Start, template<class U, U Arg> class Expression> struct For'| C:\\src\\partial.cpp|18|error: expected a template of type \template<class U, U Arg> class Expression', got `template<class U, U Arg> class Expression'|
C:\src\partial.cpp|34|instantiated from here|
C:\src\partial.cpp|27|error:CallReduce<unsigned int, 2u>::result' cannot be initialized by a non-constant expression when being declared| C:\\src\\partial.cpp||In functionint main()':|
C:\src\partial.cpp|34|warning: statement has no effect|
||=== Build finished: 5 errors, 1 warnings ===|Compiler ist MinGW der CodeBlocks Version 0.8.2 (G++ 3.4.5?)
-
In den Zeilen 12, 17 und 19 hat das Schlüsselwort template nichts zu suchen.
In Zeile 19 Start soll vermutlich 0 sein.
Grundsätzlich liegt das Problem an anderer Stelle: der Typ eines Non-type Arguments einer partiellen Spezialisierung darf nicht abhängig (von einem Parameter dieser Spezialisierung) sein (14.5.5/9 2. Alt.). Weshalb dies Restriktion existiert, ist mir nicht bekannt, ich vermute, dass es zu Mehrdeutigkeiten führen könnte.
Selbstverständlich gibt es einen Ausweg - die allseits beliebte Indirektion: indem wir das Non-Type-Argument in einen Typ stecken, und ein Abbruchprädikat benutzen (hier der Bequemlichkeit wegen als extra Parameter mit Defaultargument)template<typename T, T Factor> struct Reduce { static const T result = 0; }; template<typename T, T v> struct value_type { typedef T type; static const T value = v; }; template<typename Start, template<class U, U Arg> class Expression, bool end_recursion = ( Start::value == 0 )> struct For { static const typename Start::type result = For<value_type<typename Start::type, Start::value - 1>, Expression>::result; }; template<typename Start, template<class U, U Arg> class Expression> struct For<Start, Expression, true> { static const typename Start::type result = Expression<typename Start::type, Start::value>::result; }; template<typename T, T Arg> struct CallReduce { static const T result = For<value_type<T, Arg>, Reduce>::result; }; int main() { CallReduce<unsigned, 2u>::result; }Geht vermutlich noch eleganter, das hier nur schnell hingeschrieben.
-
danke für den tipp, ich habe es jetzt zum laufen gebracht, allerdings etwas anders:
template<typename T, T ArgA, T ArgB> struct NoDiff { static const bool result = (ArgB - ArgA) == 0; };danach habe ich ein extra-argument "bool Quit" in die template-liste von For eingefügt und entsprechend spezialisiert.