什么是C++中未评估的上下文
What are unevaluated contexts in C++?
经常想到的一个例子是:
sizeof
表达式,它不计算表达式,而是按静态类型确定大小。例如:
int func();
sizeof(func());
这是我的思维极限,所以如果还有其他未评估的上下文,那么它们是什么?
幸运的是,该标准有一个方便的列表(§ 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
};
typeid
§ 5.2.8 [expr.typeid] ¶ 3:
当
typeid
应用于多态类类型的 glvalue 以外的表达式时,结果将引用表示表达式的静态类型的std::type_info
对象。左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 转换不应用于表达式。如果表达式的类型是类类型,则应完全定义该类。表达式是未计算的操作数 (第5条)。
请注意多态类(至少具有一个virtual
成员的class
)强调的异常。
因此,这没关系
typeid( foo() )
并生成一个std::type_info
对象用于int
而
typeid( widget::get_instance() )
不是,并且可能会产生链接时错误。它必须计算操作数,因为动态类型是通过在运行时查找vptr
来确定的。
sizeof
§ 5.3.3 [扩展大小] ¶ 1:
sizeof
运算符在其操作数的对象表示形式中生成字节数。操作数可以是表达式(即未计算的操作数(条款 5),也可以是带括号的类型 ID。sizeof
运算符不得应用于具有函数或不完整类型的表达式、其基础类型在声明其所有枚举器之前未固定的枚举类型、此类类型的括号名称或指定位字段的 glvalue。
以下
sizeof( foo() )
完全没问题,相当于sizeof(int)
.
sizeof( widget::get_instance() )
也是允许的。但请注意,它等效于sizeof(widget)
,因此在多态return
类型上可能不是很有用。
noexcept
§ 5.3.7 [expr.unary.noexcept] ¶ 1:
noexcept
运算符确定其操作数(即未计算的操作数(条款 5))的计算是否可以引发异常 (15.1)。
表达式
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
的变量n
,并使用值 42 对其进行初始化。
auto baz() -> decltype( widget::get_instance() );
声明一个不带参数的函数baz
,return
widget&
。
这就是全部(截至 C++14)。
标准项是一个未计算的操作数,你可以在 [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 涵盖了简单的类型说明符,如
auto
和decltype
和 POD 类型,如int
、char
、double
等。
- std::condition_variable::wait()如何评估给定的谓词
- #为""定义宏;静态";针对不同的上下文
- 与互斥锁相比,旋转锁可以保证上下文切换
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- 为什么我不能使用 EGL 创建无头 OpenGl 上下文?
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- c++11评估顺序(未定义的行为)
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- 错误"Could not find Boost"(缺少:上下文标头)
- 使用 mod_gsoap 部署服务时,如何在 Gsoap 中更改 soap 上下文的模式?
- 如何使用"equal to"以外的评估编写开关语句
- 嵌套 if 中没有返回评估
- 懒惰的参数评估try_emplace?
- 将有状态的 lambda 传递到 C 样式函数中,而无需上下文参数
- 在实践中,在运行时为零的乘法中是否有任何"lazy"评估
- 安排带有上下文的协同程序
- 我的文件无法正常工作,无法从C++文件中读取上下文
- MSVC 在不知道类型的情况下评估上下文(和错误)
- 如何在未评估的上下文中将成员函数的结果类型应用于类成员
- 什么是C++中未评估的上下文