c++ - trailing return type using decltype with a variadic template function -


i want write simple adder (for giggles) adds every argument , returns sum appropriate type. currently, i've got this:

#include <iostream> using namespace std;  template <class t> t sum(const t& in) {    return in; }  template <class t, class... p> auto sum(const t& t, const p&... p) -> decltype(t + sum(p...)) {    return t + sum(p...); }  int main() {    cout << sum(5, 10.0, 22.2) << endl; } 

on gcc 4.5.1 seems work fine 2 arguments e.g. sum(2, 5.5) returns 7.5. however, more arguments this, errors sum() not defined yet. if declare sum() however:

template <class t, class p...> t sum(const t& t, const p&... p); 

then works number of arguments, sum(2, 5.5) return integer 7, not expect. more 2 arguments assume decltype() have sort of recursion able deduce type of t + sum(p...). legal c++0x? or decltype() work non-variadic declarations? if case, how write such function?

i think problem variadic function template considered declared after specified return type sum in decltype can never refer variadic function template itself. i'm not sure whether gcc bug or c++0x doesn't allow this. guess c++0x doesn't allow "recursive" call in ->decltype(expr) part.

as workaround can avoid "recursive" call in ->decltype(expr) custom traits class:

#include <iostream> #include <type_traits> using namespace std;  template<class t> typename std::add_rvalue_reference<t>::type val();  template<class t> struct id{typedef t type;};  template<class t, class... p> struct sum_type; template<class t> struct sum_type<t> : id<t> {}; template<class t, class u, class... p> struct sum_type<t,u,p...> : sum_type< decltype( val<const t&>() + val<const u&>() ), p... > {}; 

this way, can replace decltype in program typename sum_type<t,p...>::type , compile.

edit: since returns decltype((a+b)+c) instead of decltype(a+(b+c)) closer how use addition, replace last specialization this:

template<class t, class u, class... p> struct sum_type<t,u,p...> : id<decltype(       val<t>()     + val<typename sum_type<u,p...>::type>() )>{}; 

Comments