下面的代码适用于:左关联求和操作的目标:sum(1,2,3,4);
但是,对于sum(1,2,3,4,5)
或sum(1,2,3,4,5,...)
,它无法正常工作。任何超过4个参数的内容都会出现错误:
错误:调用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
}
当使用可变参数模板,自动返回类型以及对尾随返回类型中的相同可变参数模板的递归引用时,这似乎是GCC中的一个错误。
C ++ 11 - 只有正确的关联
它可以通过良好的旧模板元编程来解决:
//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:更加通用,整个事情可能会受到“普遍参考”和std::forward
的影响。
C ++ 17倍表达式
在C ++ 17中,问题基本上可以在一行中解决:
template<typename T, typename... Ts>
constexpr auto sum(T&& t, Ts&&... ts)
{
return (std::forward<T>(t) + ... + std::forward<Ts>(ts));
}
``
该功能需要额外检查:
#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;
}
并且它更好地通过价值。
否则我们会得到奇怪的结果:
int main() {
std::cout << sum(1,"Hello World");
return 0;
}