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

Ang*_*tis 44 c++ c++11

经常浮现的一个例子是:

sizeof表达式,它不计算表达式,但通过静态类型确定大小.例如 :

int func();
sizeof(func());
Run Code Online (Sandbox Code Playgroud)

这是我思考的极限,所以如果还有其他未评估的背景,那么它们是什么?

5go*_*der 38

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

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

让我们详细看看这些.

我将在我的示例中使用以下声明.声明的函数永远不会在任何地方定义,因此如果对它们的调用出现在评估的上下文中,则程序格式错误,我们将得到链接时错误.然而,在未评估的环境中调用它们很好.

int foo();  // never defined anywhere

struct widget
{
  virtual ~widget();
  static widget& get_instance();  // never defined anywhere
};
Run Code Online (Sandbox Code Playgroud)

typeid

§5.2.8[expr.typeid]3:

typeid应用于多态类类型的glvalue以外的表达式时,结果引用std::type_info表示表达式的静态类型的对象.Lvalue-to-rvalue(4.1),数组到指针(4.2)和函数到指针(4.3)转换不应用于表达式.如果表达式的类型是类类型,则应完全定义类.表达式是未评估的操作数(第5条).

注意多态类的强调异常(a class至少有一个virtual成员).

因此,这没关系

typeid( foo() )
Run Code Online (Sandbox Code Playgroud)

并为此产生一个std::type_info对象int

typeid( widget::get_instance() )
Run Code Online (Sandbox Code Playgroud)

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

<rant>我发现操作数的静态类型是否具有多态性这一事实会以如此戏剧性但微妙的方式改变运算符的语义,这让我感到非常困惑.</ rant>

sizeof

§5.3.3[expr.sizeof]1:

sizeof操作者产生在其操作数的对象表示的字节数.操作数是一个表达式,它是一个未评估的操作数(第5章),或带括号的type-id.sizeof在声明所有枚举数之前,运算符不应该应用于具有函数或不完整类型的表达式,其基础类型未固定的枚举类型,此类型的带括号的名称,或者指定位的glvalue -领域.

下列

sizeof( foo() )
Run Code Online (Sandbox Code Playgroud)

非常好,相当于sizeof(int).

sizeof( widget::get_instance() )
Run Code Online (Sandbox Code Playgroud)

也是允许的.但请注意,它sizeof(widget)与多态return类型相当,因此可能不太有用.

noexcept

§5.3.7[expr.unary.noexcept]1:

noexcept操作员确定的评估是否它的操作数,这是一个未计算的操作数(第5章),可以抛出异常(15.1).

表达方式

noexcept( foo() )
Run Code Online (Sandbox Code Playgroud)

是有效的,并评估为false.

这是一个更实际的例子,也是有效的.

void bar() noexcept(noexcept( widget::get_instance() ));
Run Code Online (Sandbox Code Playgroud)

请注意,只有内部noexcept是操作符,而外部是说明符.

decltype

§7.1.6.2[dcl.type.simple]4.4:

说明符的操作数decltype是未评估的操作数(第5条).

该声明

decltype( foo() ) n = 42;
Run Code Online (Sandbox Code Playgroud)

声明一个n类型的变量int并用值42初始化它.

auto baz() -> decltype( widget::get_instance() );
Run Code Online (Sandbox Code Playgroud)

声明一个baz不带参数和returnsa 的函数widget&.

这就是全部(从C++ 14开始).

  • `auto`与`decltype`在同一部分中引入,但我不知道它是如何成为未评估的上下文.它甚至不需要操作数.在第7.1.6.2段中出现"未评估"一词的唯一时间是在我的答案中引用的段落中.但IANAL. (2认同)
  • @vsoftco 因为 `singleton` 是多态的,该表达式会生成运行时代码以跟随 `vptr`。这意味着对未定义函数 `singleton::get_instance` 的实际调用。请参阅标准引用中第一个突出显示的句子。就个人而言,我觉得这种棘手的差异有点尴尬。 (2认同)

Nat*_*ica 8

标准术语是未评估的操作数,您可以在[expr]中找到它

在某些情况下,出现了未评估的操作数(5.2.8,5.3.3,5.3.7,7.1.6.2).未评估未评估的操作数.未评估的操作数被视为完整表达式.[注意:在未评估的操作数中,可以将非静态类成员命名为(5.1),并且对象或函数的命名本身不要求提供定义(3.2). - 尾注]

  • 5.2.8封面 typeid
  • 5.3.3封面 sizeof
  • 5.3.7封面 noexcept
  • 7.1.6.2覆盖简单类型说明符如autodecltype和POD类型,如int,char,double等.