常量求值中dynamic_cast的行为:程序是否合法?输出应为多少?
常量求值场景下构造函数内
dynamic_cast的行为问题 #include <iostream> struct A { constexpr A(); virtual void f() {} bool x; }; struct B : A {}; constexpr A::A() { x = dynamic_cast<B*>(this); } constexpr bool b = B{}.x; int main() { std::cout << B{}.x << b; }
现象说明
- 普通求值时,
main中B{}.x输出0:在基类A的构造函数执行期间,对象的动态类型是A(派生类B的成员尚未构造),此时dynamic_cast<B*>(this)返回nullptr,赋值给bool类型的x后结果为false(即0)。 - 常量求值时各编译器行为分歧:
- Clang输出第二个
0,符合预期; - MSVC输出第二个
1,错误判定dynamic_cast返回非空指针; - GCC报错,认为
constexpr bool b = B{}.x不是合法的常量表达式。
- Clang输出第二个
问题解答
程序是否定义良好?
该程序符合C20及后续标准,是定义良好的。C20允许在constexpr构造函数中使用dynamic_cast,只要转换操作在常量求值上下文中的结果是确定的:此处转换必然失败返回nullptr,将nullptr转换为bool得到false,属于合法的常量表达式。
正确输出应为多少?
正确输出是00。无论普通求值还是常量求值,在A的构造函数执行阶段,对象的动态类型始终是A(派生类B的构造尚未完成),因此dynamic_cast<B*>(this)必然返回nullptr,x的值始终为false(即0)。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

