templates + rekursion
-
Hi, ich arbeite mich gerade ein bischen in template metaprogramming und die C++11 Features ein. Dabei stoße ich auf folgendes Problem:
template <size_t N> struct n { static const size_t value = N; }; template <typename...Args> constexpr size_t size_of() { return sizeof...(Args); } template <typename T, typename...Args> typename std::enable_if<(size_of<Args...>() > 0), size_t>::type sum() { return T::value + sum<Args...>(); } template <typename T, typename...Args> typename std::enable_if<(size_of<Args...>() == 0), size_t>::type sum() { return T::value; } int main(int argc, char **argv) { sum<n<2>,n<7>>(); }
gcc 4.8.2 20140206 schrieb:
/var/projects/mg/src/ffuzz/main.cpp: In instantiation of ‘typename std::enable_if<(size_of<Args ...>() > 0), long unsigned int>::type sum() [with T = n<2ul>; Args = {n<7ul>}; typename std::enable_if<(size_of<Args ...>() > 0), long unsigned int>::type = long unsigned int]’:
/var/projects/mg/src/ffuzz/main.cpp:38:31: required from here
/var/projects/mg/src/ffuzz/main.cpp:26:36: error: no matching function for call to ‘sum()’
return T::value + sum<Args...>();
^
/var/projects/mg/src/ffuzz/main.cpp:26:36: note: candidate is:
/var/projects/mg/src/ffuzz/main.cpp:25:1: note: template<class T, class ... Args> typename std::enable_if<(size_of<Args ...>() > 0), long unsigned int>::type sum()
sum() {
^
/var/projects/mg/src/ffuzz/main.cpp:25:1: note: template argument deduction/substitution failed:
/var/projects/mg/src/ffuzz/main.cpp: In substitution of ‘template<class T, class ... Args> typename std::enable_if<(size_of<Args ...>() > 0), long unsigned int>::type sum() [with T = n<7ul>; Args = {}]’:
/var/projects/mg/src/ffuzz/main.cpp:26:36: required from ‘typename std::enable_if<(size_of<Args ...>() > 0), long unsigned int>::type sum() [with T = n<2ul>; Args = {n<7ul>}; typename std::enable_if<(size_of<Args ...>() > 0), long unsigned int>::type = long unsigned int]’
/var/projects/mg/src/ffuzz/main.cpp:38:31: required from here
/var/projects/mg/src/ffuzz/main.cpp:25:1: error: no type named ‘type’ in ‘struct std::enable_if<false, long unsigned int>’Warum scheitert der Compiler beim Rekursionsanker? Ich verstehe gerade nicht, warum hier nicht Variante 2 ausgewählt wird.
-
Falsche Reihenfolge bei der Definition. Kompilierst du es mit Clang, gibt er dir auch eine schöne Erklärung.
-
Ich verstehe gerade nicht, warum hier nicht Variante 2 ausgewählt wird.
Ich verstehe nicht, warum sie das sollte.
§14.6/1 schrieb:
Three kinds of names can be used within a template definition:
— The name of the template itself, and names declared within the template itself.
— Names dependent on a template-parameter (14.6.2).
— Names from scopes which are visible within the template definition.Und
sum
ist nicht abhängig, weil weder der Name selbst -sum
- abhängig ist, noch eines der Argumente für den Funktionsaufruf.Übrigens würde das auch mit einem abhängigen Argument nicht funktionieren, weil ADL - grob gesagt - nur auf Funktionsaufrufe ohne explizite Template-Argumente funktioniert (§14.8.1/8).