C ++中未评估的上下文是什么?
经常想到的一个例子是:
sizeof
expression式,它不计算expression式,但是通过静态types来确定大小。 例如 :
int func(); sizeof(func());
这是我思考的极限,所以如果还有其他未被评估的情境,那么它们是什么?
幸运的是,标准有一个方便的列表(§5 [expr]¶8):
在某些情况下,出现未评估的操作数 (5.2.8,5.3.3,5.3.7,7.1.6.2)。 未评估的操作数未被评估。 一个未被评估的操作数被认为是一个完整的expression式。
我们来仔细看看这些。
我将在我的例子中使用下面的声明。 声明的函数从来没有在任何地方定义过,所以如果一个调用它们出现在一个评估的上下文中,程序是不合格的,我们将得到一个链接时间错误。 然而,在没有评估的情况下调用它们是很好的。
int foo(); // never defined anywhere struct widget { virtual ~widget(); static widget& get_instance(); // never defined anywhere };
typeid
§5.2.8 [expr.typeid]¶3:
当
typeid
应用于除多态类types的glvalue以外的expression式时 ,结果引用表示expression式的静态types的std::type_info
对象。 左值到右值(4.1),数组到指针(4.2)和函数到指针(4.3)的转换不适用于expression式。 如果expression式的types是一个类的types,那么该类将被完全定义。 expression式是一个未评估的操作数(第5章)。
注意多态类(一个至less有一个virtual
成员的类)的强调exception。
所以,这没关系
typeid( foo() )
并为此产生一个std::type_info
对象
typeid( widget::get_instance() )
不是,可能会产生链接时间错误。 它必须评估操作数,因为dynamictypes是通过在运行时查找vptr
来确定的。
我发现这样一个事实令人困惑:操作数的静态types是否是多态的,会以如此戏剧性而又微妙的方式改变操作符的语义。</ rant>
sizeof
§5.3.3 [expr.sizeof]¶1:
sizeof
运算符产生其操作数的对象表示forms中的字节数。 操作数是一个expression式,它是一个未被评估的操作数(条款5) ,或者是一个带括号的types标识符 。sizeof
运算符不能被应用到一个具有函数或不完整types的expression式,在枚举types的基本types在其所有枚举符被声明之前是不固定的,也可能被应用到这种types的括号中,或者指定一个glvalue位字段。
下列
sizeof( foo() )
是完全正确的,相当于sizeof(int)
。
sizeof( widget::get_instance() )
也是允许的。 但是请注意,它相当于sizeof(widget)
,因此对于多态return
types可能不是很有用。
noexcept
§5.3.7 [expr.unary.noexcept]¶1:
noexcept
操作符确定操作数(未评估的操作数(第5章))的评估是否可以抛出exception(15.1)。
expression方式
noexcept( foo() )
是有效的并且评估为false
。
这是一个更现实的例子,也是有效的。
void bar() noexcept(noexcept( widget::get_instance() ));
请注意,只有内部noexcept
是运算符,而外部是说明符。
decltype
§7.1.6.2 [dcl.type.simple]¶4.4:
decltype
说明符的操作数是一个未评估的操作数(第5章)。
该声明
decltype( foo() ) n = 42;
声明一个int
types的variablesn
并用值42初始化它。
auto baz() -> decltype( widget::get_instance() );
声明一个不带参数的函数baz
,并return
一个sa widget&
。
这就是所有(就像C ++ 14一样)。
标准术语是一个未评估的操作数 ,您可以在[expr]
在某些情况下,出现未评估的操作数(5.2.8,5.3.3,5.3.7,7.1.6.2)。 未评估的操作数未被评估。 一个未被评估的操作数被认为是一个完整的expression式。 [注意:在一个未评估的操作数中,非静态类成员可以被命名为(5.1),而对象或函数的命名本身并不要求提供定义(3.2)。 – 注意]
- 5.2.8涵盖了
typeid
- 5.3.3涵盖了
sizeof
- 5.3.7涵盖
noexcept
- 7.1.6.2包含简单的types说明符,如
auto
,decltype
和PODtypes,如int
,char
,double
等