Bar*_*rry 13 c++ throw language-lawyer c++14
考虑片段:
try {
Foo f;
throw std::move(f);
}
catch (Foo& f) { }
Run Code Online (Sandbox Code Playgroud)
[expr.throw]说:
异常对象的类型是通过从操作数的静态类型中删除任何顶级cv限定符并将类型从"T的数组"或"返回T的函数"调整为"指向T的指针"或"指针"来确定的.函数返回T",分别.
这将是Foo&&.然后根据[except.throw]初始化异常对象:
抛出异常copy-initializes(8.5,12.8)一个临时对象,称为异常对象.临时是一个左值,用于初始化匹配处理程序中声明的变量(15.3).如果异常对象的类型是不完整类型或指向不完整类型的指针(可能是cv-qualified),
void则程序格式不正确.
这告诉我异常对象被初始化为:
Foo&& __exception_object = std::move(f);
Run Code Online (Sandbox Code Playgroud)
并且处理程序不匹配.但是,gcc和clang都会捕获此异常.那么这里的异常对象的实际类型是什么?如果Foo,为什么?
Jon*_*ely 14
表达式的静态类型永远不是引用类型.
1.3.24 [defns.static.type]定义"静态类型":
在不考虑执行语义的情况下对程序进行分析得到的表达式(3.9)的类型
"分析程序"的第一步是删除引用,参见5 [expr] p5,表达式可以有引用类型
如果表达式最初具有"引用
T" 类型(8.3.2,8.5.3),则T在进行任何进一步分析之前调整类型.表达式指定由引用表示的对象或函数,表达式是左值或x值,具体取决于表达式.
std::move(f)xvalue表达式也是如此,具有静态类型Foo.
你不需要让rvalues来证明这一点,在C++ 03中也是如此:
int& f();
throw f();
Run Code Online (Sandbox Code Playgroud)
这引发了int不是int&.
在不考虑细节的情况下,异常对象是对象,而引用不是对象,因此异常对象不能作为引用.它必须是一个对象.
| 归档时间: |
|
| 查看次数: |
300 次 |
| 最近记录: |