我想编写一个简单的加法器(用于咯咯笑),它将每个参数相加并返回具有适当类型的总和。 目前,我有这个:
#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() 仅适用于非可变声明?如果是这样,您将如何编写这样的函数?
最佳答案
我认为问题在于可变参数函数模板仅在您指定其返回类型之后才被视为声明,因此sum
在 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>()
)>{};
关于c++ - 使用带有可变参数模板函数的 decltype 的尾随返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3744400/