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

标签 c++ templates c++11 variadic-functions 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() 仅适用于非可变声明?如果是这样,您将如何编写这样的函数?

最佳答案

我认为问题在于可变参数函数模板仅在您指定其返回类型之后才被视为声明,因此sumdecltype永远不能引用可变参数函数模板本身。但我不确定这是 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/

相关文章:

c++ - OpenCV calcHist 函数。

c++ - SFGUI 渲染问题 C++

json - 通过 CLI 进行 Azure ARM 模板部署失败,并出现 .ps1 脚本扩展错误

C++11 g++ 奇怪(使用默认模板、lambda 和 remove_if)

c++ - 有没有办法将数据从 vector 移动到动态数组?

windows - 我可以在 Windows 上使用 std::thread 吗?

c++ - 多线程暴力和递归多维循环。其他方式?

c++ - 为后缀重载一元运算符

c++ - 从其他容器中辨别 smart_pointer 的模板函数

c++ - 如何确保 win-builder 使用 c++11 构建我的包?