使用带有可变参数模板函数的 decltype 的尾随返回类型 [英] trailing return type using decltype with a variadic template function

查看:25
本文介绍了使用带有可变参数模板函数的 decltype 的尾随返回类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to write a simple adder (for giggles) that adds up every argument and returns a sum with appropriate type. Currently, I've got this:

#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() :

On GCC 4.5.1 this seems to work just fine for 2 arguments e.g. sum(2, 5.5) returns with 7.5. However, with more arguments than this, I get errors that sum() is simply not defined yet. If I declare sum() like this however:

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() 仅适用于非可变参数声明?如果是这样,您将如何编写这样的函数?

Then it works for any number of arguments, but sum(2, 5.5) would return integer 7, which is not what I would expect. With more than two arguments I assume that decltype() would have to do some sort of recursion to be able to deduce the type of t + sum(p...). Is this legal C++0x? or does decltype() only work with non-variadic declarations? If that is the case, how would you write such a function?

推荐答案

我认为问题在于可变参数函数模板仅在您指定其返回类型之后才被考虑声明,以便 sumdecltype 中的 永远不能引用可变参数函数模板本身.但我不确定这是 GCC 错误还是 C++0x 根本不允许这样做.我的猜测是 C++0x 不允许在 ->decltype(expr) 部分进行递归"调用.

I think the problem is that the variadic function template is only considered declared after you specified its return type so that sum in decltype can never refer to the variadic function template itself. But I'm not sure whether this is a GCC bug or C++0x simply doesn't allow this. My guess is that C++0x doesn't allow a "recursive" call in the ->decltype(expr) part.

作为一种解决方法,我们可以在 ->decltype(expr) 中使用自定义特征类避免这种递归"调用:

As a workaround we can avoid this "recursive" call in ->decltype(expr) with a custom traits class:

#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::type 替换你程序中的 decltype 并且它会编译.

This way, we can replace decltype in your program with typename sum_type<T,P...>::type and it will compile.

因为这实际上返回 decltype((a+b)+c) 而不是 decltype(a+(b+c)) 这将更接近于您如何使用加法,您可以用这个替换最后一个专业化:

Since this actually returns decltype((a+b)+c) instead of decltype(a+(b+c)) which would be closer to how you use addition, you could replace the last specialization with this:

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

这篇关于使用带有可变参数模板函数的 decltype 的尾随返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆