7

下面的代码适用于:左关联求和运算的目标:sum(1,2,3,4);

sum(1,2,3,4,5)但是,它对于or将无法正常工作 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

}
4

2 回答 2

5

这似乎是 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));
}
``
于 2013-05-21T07:26:21.673 回答
2

该功能需要额外检查:

#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;
}
于 2014-09-14T08:08:03.033 回答