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

std::declval是一个编译时间实用程序,用于构buildexpression式以确定其types。 它是这样定义的:

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

这不是更简单吗?

 template< class T > T declval() noexcept; 

引用返回types的优点是什么? 不应该叫做declref

我发现的最早的历史例子是n2958 ,它调用函数的value()但总是返回一个引用。

注意, decltype的操作数不需要有一个可访问的析构函数,也就是说,它不是在语义上被检查为一个完整的expression式。

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

只有在函数调用本身是decltype的操作数,或者作为decltype的操作数的逗号运算符的右操作数时,“适用于在decltype返回对象types的函数的临时函数”(§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将阻止大多数不完整types的非重要用法,带有私有析构函数的types等等:

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

这样做几乎没有什么好处,因为xvalues与prvalues几乎没有什么区别,除非使用decltype ,并且通常不会直接在declval的返回值上使用decltype – 您已经知道types。

数组不能返回值,因此即使只是声明一个函数返回一个数组是无效的代码。

但是,您可以通过引用返回一个数组。

decltype()的目的是要有一个expression式作为T的有效值,把它作为expressionT的expression式。 问题是,在C ++中,typesT可以是不可复制的,甚至是非默认可构造的。 所以使用T{}来达到这个目的是行不通的。

decltype()所做的是将一个右值引用返回给T 右值引用对于任何typesT都应该是有效的,所以它保证我们有一个来自T的右值引用的有效的T ,并且保证我们可以有任何typesT的右值引用。 这就是诀窍。

考虑decltype()为“ 给我一个T型的有效expression式 ”。 当然它的用途是用于重载分辨率,types确定等。 因为它的目的是返回一个有效的expression式 (在语法上),而不是返回一个值。 这反映在std::declval()没有被定义的事实,它唯一的声明。
如果定义了,我们又有了最初的问题(我们必须为任意typesT构造一个值,而这是不可能的)。