什么是C的未评估的上下文?

经常想到的一个例子是:

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

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

这是我的思考极限,所以如果有其他未评估的上下文,那么他们是什么?

幸运的是,标准有一个方便的列表(§5 [expr]¶8):

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.

让我们来详细看看这些。

我将在我的示例中使用以下声明。声明的函数从不在任何地方定义,因此如果对它们的调用出现在评估的上下文中,程序是不成形的,我们将得到链接时间错误。然而,在未经评估的环境中调用它们是很好的。

int foo();  // never defined anywhere

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

typeid

§5.2.8 [expr.typeid]¶3:

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).

注意多态类(一个具有至少一个虚拟成员的类)强调的异常。

因此,这是好的

typeid( foo() )

并产生一个std :: type_info对象为int,而这

typeid( widget::get_instance() )

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

< rant>我发现很容易混淆的是,操作数的静态类型是否是多态性的事实以这种戏剧性的,但微妙的方式改变了操作符的语义。

sizeof

§5.3.3 [expr.sizeof]¶1:

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),因此可能不是非常有用的多态返回类型。

noexcept

§5.3.7 [expr.unary.noexcept]¶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() )

是有效的并且计算结果为假。

这是一个更现实的例子,也是有效的。

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

注意,只有内部noexcept是运算符,而outer是说明符。

decltype

§7.1.6.2 [dcl.type.simple] 4.4:

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

该声明

decltype( foo() ) n = 42;

声明类型为int的变量n,并将其初始化为值42。

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

声明一个不带参数并返回一个小部件的函数baz。

这就是所有的(作为C 14)。

http://stackoverflow.com/questions/35088599/what-are-unevaluated-contexts-in-c

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:什么是C的未评估的上下文?