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
答案 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}}构造一个值,这是不可能的。)