使用带有可变参数模板函数的decltype的尾随返回类型

我想编写一个简单的加法器(用于傻笑),将每个参数加起来并返回具有适当类型的和。目前,我有这个:


#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;

}

在GCC 4.5.1上,这似乎可以很好地用于2个参数,例如sum(2,5.5)返回7.5。但是,使用了比这更多的参数,我得到的错误是尚未定义sum()。如果我这样声明sum():


template <class T, class P...>

T sum(const T& t, const P&... p);

然后它适用于任意数量的参数,但是sum(2,5.5)将返回整数7,这不是我期望的。对于两个以上的参数,我认为decltype()必须进行某种递归才能得出t + sum(p ...)的类型。这是合法的C ++ 0x吗?还是decltype()仅适用于非变量声明?如果是这样,您将如何编写这样的函数?


拉风的咖菲猫
浏览 466回答 3
3回答

慕村9548890

我认为问题在于,可变参数函数模板仅在您指定其返回类型后才视为已声明,因此sumin decltype永远无法引用可变参数函数模板本身。但是我不确定这是GCC错误还是C ++ 0x根本不允许这样做。我的猜测是C ++ 0x不允许在->decltype(expr)零件中进行“递归”调用。作为解决方法,我们可以避免->decltype(expr)使用自定义特征类进行此“递归”调用:#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... > {};这样,我们可以将decltype您的程序替换为typename sum_type<T,P...>::type并进行编译。编辑:由于这实际上返回,decltype((a+b)+c)而不是decltype(a+(b+c))更接近于您使用加法的方式,因此您可以用此替换最后一个专业化:template<class T, class U, class... P> struct sum_type<T,U,P...>: id<decltype(&nbsp; &nbsp; &nbsp; val<T>()&nbsp; &nbsp; + val<typename sum_type<U,P...>::type>())>{};

holdtom

C ++ 14的解决方案:template <class T, class... P>auto sum(const T& t, const P&... p){&nbsp; &nbsp; return t + sum(p...);}返回类型自动扣除。

偶然的你

显然,您不能以递归方式使用decltype(至少目前是这样,也许他们会解决它)您可以使用模板结构来确定总和的类型看起来很丑但是可以用#include <iostream>using namespace std;template<typename... T>struct TypeOfSum;template<typename T>struct TypeOfSum<T> {&nbsp; &nbsp; typedef T&nbsp; &nbsp; &nbsp; &nbsp;type;};template<typename T, typename... P>struct TypeOfSum<T,P...> {&nbsp; &nbsp; typedef decltype(T() + typename TypeOfSum<P...>::type())&nbsp; &nbsp; &nbsp; &nbsp; type;};template <class T>T sum(const T& in){&nbsp; &nbsp;return in;}template <class T, class... P>typename TypeOfSum<T,P...>::type sum(const T& t, const P&... p){&nbsp; &nbsp;return t + sum(p...);}int main(){&nbsp; &nbsp;cout << sum(5, 10.0, 22.2) << endl;}
打开App,查看更多内容
随时随地看视频慕课网APP