为什么std :: declval添加引用?

时间:2014-09-07 05:44:57

标签: c++ c++11 decltype

std::declval是一个编译时实用程序,用于构造表达式以确定其类型。它的定义如下:

template< class T >
typename std::add_rvalue_reference<T>::type declval() noexcept;

这不会更简单吗?

template< class T >
T declval() noexcept;

参考返回类型的优点是什么?不应该被称为declref

我找到的最早的历史示例是n2958,它调用函数value()但已经始终返回引用。

注意,decltype的操作数不需要具有可访问的析构函数,即它不会在语义上被检查为完整表达式。

template< typename t >
t declprval() noexcept;

class c { ~ c (); };
decltype ( declprval< c >() ) * p = nullptr; // OK

3 个答案:

答案 0 :(得分:33)

只有当函数调用本身是decltype的操作数或逗号运算符的右操作数时,“decltype”规则中的“返回对象类型prvalue的函数才会引入临时性”。 decltype(§5.2.2[expr.call] / p11)的操作数,表示OP中给定declprval

template< typename t >
t declprval() noexcept;

class c { ~ c (); };

int f(c &&);

decltype(f(declprval<c>())) i;  // error: inaccessible destructor

无法编译。更一般地说,返回T会阻止declval使用不完整类型的大多数非常重要的用法,使用私有析构函数键入等等:

class D;

int f(D &&);

decltype(f(declprval<D>())) i2;  // doesn't compile. D must be a complete type

并且这样做几乎没有什么好处,因为xvalues与prvalues几乎无法区分,除非你对它们使用decltype,并且你通常不直接在{{1}的返回值上使用decltype你已经知道了这个类型。

答案 1 :(得分:10)

无法通过值返回数组,因此即使只是按值返回数组的函数声明也是无效代码。

但您可以通过引用返回数组。

答案 2 :(得分:3)

decltype()的目的是让一个表达式充当T类型的有效值,将其作为T放在期望T s的表达式中。问题是在C ++中,类型T可以是不可复制的,甚至是非默认可构造的。因此,为此目的使用T{}并不起作用。

decltype()的作用是返回对T的右值引用。右值引用应该对任何类型T都有效,因此它保证我们从T的右值引用中得到有效的T,并保证我们可以对任何类型的T进行右值引用输入decltype()。这就是诀窍。

T视为&#34; 为我提供类型为std::declval() &#34;的有效表达式。当然它的用途是用于重载分辨率,类型确定等;因为它的目的是返回一个有效表达式(在语法意义上),而不是返回一个值。这反映在T根本没有定义,它只被宣布的事实 如果已定义,我们又会遇到初始问题(我们必须为任意类型{{1}}构造一个值,这是不可能的。)