什么是C ++中未评估的上下文? [英] What are unevaluated contexts in C++?

查看:63
本文介绍了什么是C ++中未评估的上下文?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个经常想到的例子是:

One example that frequently comes to mind is :

sizeof 表达式,它不评估表达式,但按静态类型确定大小。例如:

sizeof expression, where it doesn't evaluates the expression but determines the size by static type. For example :

int func();
sizeof(func());

这是我的思维极限,因此,如果还有其他未评估的上下文,那么它们是什么? / p>

This is my limit of thinking, so if there are other unevaluated contexts, then what are they?

推荐答案

幸运的是,该标准提供了方便的列表(§5 [expr]¶8):

Fortunately, the standard has a handy list of those (§ 5 [expr] ¶ 8):


在某些情况下,出现未求值的操作数(5.2.8、5.3.3、5.3.7、7.1.6.2)。未评估的操作数不评估。未评估的操作数被视为完整表达式。

In some contexts, unevaluated operands appear (5.2.8, 5.3.3, 5.3.7, 7.1.6.2). An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression.

让我们详细了解一下。

我将在示例中使用以下声明。声明的函数永远不会在任何地方定义,因此,如果对它们的调用出现在 evaluated 上下文中,则程序格式错误,并且会出现链接时错误。

I will use the following declarations in my examples. The declared functions are never defined anywhere so if a call to them appears in an evaluated context, the program is ill-formed and we will get a link-time error. Calling them in an unevaluated context is fine, however.

int foo();  // never defined anywhere

struct widget
{
  virtual ~widget();
  static widget& get_instance();  // never defined anywhere
};



typeid



§5.2.8 [expr.typeid]¶3:

typeid

§ 5.2.8 [expr.typeid] ¶ 3:


typeid时应用于多态类类型的glvalue以外的表达式,结果引用的是 std :: type_info 表示表达式静态类型的对象。左值到右值(4.1),数组到指针(4.2)和函数到指针(4.3)的转换不适用于表达式。如果表达式的类型是类类型,则该类应完全定义。 表达式是未计算的操作数
(第5条)。

When typeid is applied to an expression other than a glvalue of a polymorphic class type, the result refers to a std::type_info object representing the static type of the expression. Lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) conversions are not applied to the expression. If the type of the expression is a class type, the class shall be completely-defined. The expression is an unevaluated operand (Clause 5).

请注意多态类(一个,其中至少有一个虚拟成员)。

Note the emphasized exception for polymorphic classes (a class with at least one virtual member).

因此,没关系

typeid( foo() )

并为 int std :: type_info 对象c $ c>而这

and yields a std::type_info object for int while this

typeid( widget::get_instance() )

不是,可能会产生链接时错误。它必须评估操作数,因为动态类型是通过在运行时查找 vptr 来确定的。

is not and will probably produce a link-time error. It has to evaluate the operand because the dynamic type is determined by looking up the vptr at run-time.

< rant>我感到非常困惑,即操作数的静态类型是否是多态的这一事实以这种戏剧性但微妙的方式改变了运算符的语义。< / rant>

<rant>I find it quite confusing that the fact whether or not the static type of the operand is polymorphic changes the semantics of the operator in such dramatic, yet subtle, ways.</rant>

§5.3.3 [expr.sizeof]¶1:

§ 5.3.3 [expr.sizeof] ¶ 1:


sizeof 运算符产生其操作数的对象表示形式中的字节数。 操作数可以是一个表达式,可以是未计算的操作数(第5条),也可以是带括号的 type-id sizeof 运算符不适用于具有函数或不完整类型的表达式,其基础类型在声明其所有枚举器之前未固定的枚举类型,

The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 5), or a parenthesized type-id. The sizeof operator shall not be applied to an expression that has function or incomplete type, to an enumeration type whose underlying type is not fixed before all its enumerators have been declared, to the parenthesized name of such types, or to a glvalue that designates a bit-field.

以下

sizeof( foo() )

非常好,相当于 sizeof(int)

sizeof( widget::get_instance() )

。但是请注意,它等效于 sizeof(widget),因此对于多态 return 类型可能不太有用。

is allowed too. Note, however, that it is equivalent to sizeof(widget) and therefore probably not very useful on a polymorphic return type.

§5.3.7 [ expr.unary.noexcept]¶1:

§ 5.3.7 [expr.unary.noexcept] ¶ 1:


noexcept 运算符确定是否其操作数(未评估的操作数(第5条))的评估会引发异常(15.1)。

The noexcept operator determines whether the evaluation of its operand, which is an unevaluated operand (Clause 5), can throw an exception (15.1).

表达式

noexcept( foo() )

有效,且评估为 false

此处

void bar() noexcept(noexcept( widget::get_instance() ));

请注意,只有内部 noexcept

§7.1.6.2 [dcl.type.simple]¶4.4:

§ 7.1.6.2 [dcl.type.simple] ¶ 4.4:


decltype 说明符是未求值的操作数(第5条)。

The operand of the decltype specifier is an unevaluated operand (Clause 5).

该语句

decltype( foo() ) n = 42;

声明类型为<$的变量 n c $ c> int 并将其初始化为值42。

declares a variable n of type int and initializes it with the value 42.

auto baz() -> decltype( widget::get_instance() );

声明不带参数的函数 baz return sa widget&

declares a function baz that takes no arguments and returns a widget&.

仅此而已有(从C ++ 14开始)。

And that's all there are (as of C++14).

这篇关于什么是C ++中未评估的上下文?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆