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

我想写一个简单的加法器(笑),加起来每个参数,并返回与适当types的总和。 目前,我有这样的:

#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()将不得不做某种recursion来推导出t + sum(p …)的types。 这是合法的C ++ 0x吗? 还是decltype()只适用于非可变的声明? 如果是这样的话,你会怎么写这样的function呢?

我认为问题是可变参数函数模板只有您指定了返回types才会被声明为使得decltype中的sum不能引用可变参数函数模板本身。 但我不确定这是一个GCC错误还是C ++ 0x根本不允许这样做。 我的猜测是C ++ 0x不允许在->decltype(expr)部分中进行“recursion”调用。

作为一种解决方法,我们可以通过->decltype(expr)来避免这个“recursion”的调用,

 #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... > {}; 

这样,我们可以使用typename sum_type<T,P...>::typereplace程序中的decltype ,然后编译。

编辑:因为这实际上返回decltype((a+b)+c)而不是decltype(a+(b+c))这将更接近你如何使用加法,你可以用这个replace最后的专业化:

 template<class T, class U, class... P> struct sum_type<T,U,P...> : id<decltype( val<T>() + val<typename sum_type<U,P...>::type>() )>{}; 

显然你不能以recursion的方式使用decltype(至less目前来说,也许他们会修复它)

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

它看起来丑陋,但它的工作

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

C ++ 14的解决scheme:

 template <class T, class... P> auto sum(const T& t, const P&... p){ return t + sum(p...); } 

返回types是自动扣除的。

在线编译器中看到它

通过使用C ++ 11的std::common_type来减less键入的最后一个问题的另一个答案:简单地使用

 std::common_type<T, P ...>::type 

作为您的可变金额的返回types。

关于std::common_type ,这里是http://en.cppreference.com/w/cpp/types/common_type的摘录:;

对于算术types,通用types也可以看作T0()+ T1()+ … + Tn()等(可能是混合模式)算术expression式的types。

但显然这只适用于算术expression式,并不能解决一般问题。