Variable patterns summary operation left associative

The code below works for: purpose for the operation of the left associative sum: sum(1,2,3,4);

However, it will not work correctly for sum(1,2,3,4,5) or sum(1,2,3,4,5,...) . Anything with more than 4 arguments gives an error:

error: there is no corresponding function to call sum (int, int, int, int, int)

===================================

 template <typename T> T sum(const T& v) { return v; } template <typename T1, typename T2> auto sum(const T1& v1, const T2& v2) -> decltype( v1 + v2) { return v1 + v2; } template <typename T1, typename T2, typename... Ts> auto sum(const T1& v1, const T2& v2, const Ts&... rest) -> decltype( v1 + v2 + sum(rest...) ) { return v1 + v2 + sum(rest... ); } int main() { cout << sum(1,2,3,4); //works correctly //cout << sum(1,2,3,4,5); //compile error } 
+7
source share
2 answers

This seems like a mistake in GCC when working with variable templates, automatic return types, and a recursive reference to the same variable template at the end of the return type.

C ++ 11 - only associative law

This can be solved using the good old meta-programming template:

 //first a metafunction to calculate the result type of sum(Ts...) template <typename...> struct SumTs; template <typename T1> struct SumTs<T1> { typedef T1 type; }; template <typename T1, typename... Ts> struct SumTs<T1, Ts...> { typedef typename SumTs<Ts...>::type rhs_t; typedef decltype(std::declval<T1>() + std::declval<rhs_t>()) type; }; //now the sum function template <typename T> T sum(const T& v) { return v; } template <typename T1, typename... Ts> auto sum(const T1& v1, const Ts&... rest) -> typename SumTs<T1,Ts...>::type //instead of the decltype { return v1 + sum(rest... ); } #include <iostream> using std::cout; int main() { cout << sum(1,2,3,4,5); } 

PS: to be even more universal, all this could be denoted by "universal links" and std::forward .

C ++ 17 multiple expressions

In C ++ 17, the problem can be solved mainly in one line:

 template<typename T, typename... Ts> constexpr auto sum(T&& t, Ts&&... ts) { return (std::forward<T>(t) + ... + std::forward<Ts>(ts)); } '' 
+5
source

The function needs additional verification:

 #include <type_traits> template <typename T> T sum(T v) { static_assert(std::is_arithmetic<std::remove_reference<decltype(v)>::type>::value, "type should be arithmetic"); return v; } 

and better go by value.

otherwise we can get a strange result:

 int main() { std::cout << sum(1,"Hello World"); return 0; } 
+1
source

All Articles