C++ 为什么std::declval添加引用?
是一个编译时实用程序,用于构造表达式以确定其类型。定义如下:C++ 为什么std::declval添加引用?,c++,c++11,decltype,C++,C++11,Decltype,是一个编译时实用程序,用于构造表达式以确定其类型。定义如下: template< class T > typename std::add_rvalue_reference<T>::type declval() noexcept; 数组不能按值返回,因此即使函数声明按值返回数组也是无效代码 但是,您可以通过引用返回数组。decltype()的目的是让表达式充当类型为T的有效值,将其作为T的表达式中的T。问题是C++中的一个类型 t>代码>不能是可复制的,甚至是非默认可构造
template< class T >
typename std::add_rvalue_reference<T>::type declval() noexcept;
数组不能按值返回,因此即使函数声明按值返回数组也是无效代码
但是,您可以通过引用返回数组。decltype()的目的是让表达式充当类型为
T
的有效值,将其作为T
的表达式中的T
。问题是C++中的一个类型<代码> t>代码>不能是可复制的,甚至是非默认可构造的。因此,使用T{}
来达到这个目的是行不通的
decltype()
所做的是返回对T
的右值引用。右值引用应该对任何类型的T
有效,因此它保证我们从T
的右值引用中获得有效的T
,并且它保证我们可以对任何类型的T
进行右值引用。这就是诀窍
把decltype()
想象成“给我一个T
类型的有效表达式”。当然,其用途是用于过载解析、类型确定等;因为它的目的是返回一个有效的表达式(在语法意义上),而不是返回一个值。这反映在一个事实上,std::declval()
根本没有定义,只是声明了它。如果定义了它,我们又遇到了初始问题(我们必须为任意类型
T
构造一个值,这是不可能的)。在decltype
中,没有为返回对象类型的prvalue的函数引入临时值。”仅当函数调用本身是decltype
的操作数或逗号运算符的右操作数(即decltype
的操作数)(§5.2.2[expr.call]/p11)时,该规则才适用,这意味着操作中给定的declprval
template< typename t >
t declprval() noexcept;
class c { ~ c (); };
int f(c &&);
decltype(f(declprval<c>())) i; // error: inaccessible destructor
这样做几乎没有什么好处,因为xvalues与prvalues几乎没有区别,除非对它们使用
decltype
,而且您通常不会直接在declval
的返回值上使用decltype
——您已经知道该类型。要使t
成为一个有效的返回类型,难道t
不需要可复制吗T&&
可以避免这种情况。我认为这是为了支持不能按值返回的类型,例如函数类型、数组类型和抽象类。@user2357112:可移动性就足够了。@Mehrdad任何类类型都可以是返回类型,可移动性是不必要的。@Potatostater:我从来没有说过可移动性是必要的。那不是真的,T不必是可复制或可移动的,它甚至可以是不完整的,请参见@Jamboree:usingtypedef int A[4]
将使A f()代码>无效代码。我看不出这与declval
@jrok有什么关系:当t
是数组时,不能使用基于返回t
值的函数的declval
定义。我知道。但我不知道你为什么要将declval与数组类型一起使用(可能是我缺乏想象力)。啊,我没有意识到未经检查的析构函数是一个特殊的例外。我的例子完全被误导了。“没有为decltype中返回对象类型的prvalue的函数引入临时变量”变成“如果表达式是一个prvalue而不是一个(可能是括号中的)立即调用(从C++20开始),则临时对象不会从该prvalue具体化。”从C++17开始。1.我没有提议使用t{}
。2. decltype
返回右值或左值引用。
template< typename t >
t declprval() noexcept;
class c { ~ c (); };
decltype ( declprval< c >() ) * p = nullptr; // OK
template< typename t >
t declprval() noexcept;
class c { ~ c (); };
int f(c &&);
decltype(f(declprval<c>())) i; // error: inaccessible destructor
class D;
int f(D &&);
decltype(f(declprval<D>())) i2; // doesn't compile. D must be a complete type