可变参数模板总和操作左关联

alp*_*per 7 c++ templates sum decltype variadic-templates

下面的代码适用于:左关联求和操作的目标: 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

}
Run Code Online (Sandbox Code Playgroud)

Arn*_*rtz 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);    
}
Run Code Online (Sandbox Code Playgroud)

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));
}
``
Run Code Online (Sandbox Code Playgroud)

  • `std :: declval <T>()`是decltype里面`T()`的正确替代. (5认同)