为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C++
鸿蒙传说 2019-10-11 14:30:45
我想编写一个简单的加法器(用于傻笑),将每个参数加起来并返回具有适当类型的和。目前,我有这个:#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()仅适用于非变量声明?如果是这样,您将如何编写这样的函数?
查看完整描述

3 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

我认为问题在于,可变参数函数模板仅在您指定其返回类型后才视为已声明,因此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(

      val<T>()

    + val<typename sum_type<U,P...>::type>()

)>{};


查看完整回答
反对 回复 2019-10-11
?
撒科打诨

TA贡献1934条经验 获得超2个赞

C ++ 14的解决方案:


template <class T, class... P>

auto sum(const T& t, const P&... p){

    return t + sum(p...);

}

返回类型自动扣除。


查看完整回答
反对 回复 2019-10-11
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

显然,您不能以递归方式使用decltype(至少目前是这样,也许他们会解决它)


您可以使用模板结构来确定总和的类型


看起来很丑但是可以用


#include <iostream>

using namespace std;



template<typename... T>

struct TypeOfSum;


template<typename T>

struct TypeOfSum<T> {

    typedef T       type;

};


template<typename T, typename... P>

struct TypeOfSum<T,P...> {

    typedef decltype(T() + typename TypeOfSum<P...>::type())        type;

};




template <class T>

T sum(const T& in)

{

   return in;

}


template <class T, class... P>

typename TypeOfSum<T,P...>::type sum(const T& t, const P&... p)

{

   return t + sum(p...);

}


int main()

{

   cout << sum(5, 10.0, 22.2) << endl;

}


查看完整回答
反对 回复 2019-10-11
  • 3 回答
  • 0 关注
  • 528 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信