为什么std::declval添加引用
Why does std::declval add a reference?
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
只有当函数调用本身是decltype
的操作数或是作为decltype
的操作数的逗号运算符的右操作数时(§5.2.2[expr.call]/p11),"在decltype
中返回对象类型的prvalue的函数不引入临时"规则才适用,这意味着在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
,而且你通常不会直接在declval
的返回值上使用decltype
——你已经知道类型了。
数组不能按值返回,因此即使只是按值返回数组的函数声明也是无效代码。
但是,您可以通过引用返回数组。
decltype()
的目的是让一个表达式充当T
类型的有效值,并将其作为T
s的表达式中的T
。问题是,在C++中,T
类型可能是不可复制的,甚至是不可默认构造的。因此,将T{}
用于此目的是行不通的。
decltype()
所做的是返回对T
的右值引用。右值引用应该对任何类型的T
有效,因此它保证我们从T
的右值引用中获得有效的T
,并且它保证我们可以对任何类型T
具有右值引用。这就是诀窍。
将decltype()
想象为"给我一个类型为T
的有效表达式"。当然,它的用途是用于过载解析、类型确定等;因为它的目的是返回有效表达式(在语法意义上),而不是返回值。这反映在std::declval()
根本没有定义,它只是声明的
如果定义了它,我们又遇到了最初的问题(我们必须为任意类型的T
构造一个值,这是不可能的)。
- CMake VS_PACKAGE_REFERENCES不添加对 VS2017 项目的引用
- 将新元素添加到列表中,并返回对该元素的引用?
- 本机 Nuget 包安装在 VS 中,但没有为C++(本机)项目添加引用
- 将常量添加到引用
- 为什么在此 CRTP 基函数调用中添加引用会消除错误?
- 在 ONE 设置中添加附加包含目录并引用 => 指向静态库
- 在C++中向地图添加对对象的引用
- 对成员变量的引用在向同一向量中添加另一个实例后断开
- 是否有一种方法可以将C 类成员引用到向量而不明确添加它们
- 处理受向 std::vector 添加元素影响的引用
- 如何将非托管库引用添加到 NUnit 测试
- 为什么添加对右值引用的引用不是错误
- 当通过引用传递时,通过传递链表在第n个位置添加元素不起作用
- 在 CMake CMakeLists.txt 中添加对 NewT 的库引用
- 添加到字符串数组和引用
- 添加了对 .lib 项目的引用 - 项目不使用.cpp文件
- 为什么Qt会向相对不被引用的库添加'PWD'?
- 添加控制器引用/指向c++单例类的指针
- 将函数引用添加到列表中
- Visual C# - 引用 > 添加引用... > COM:该列表是如何填充的?