In following program the constructor of polymorphic struct A
tries to dynamic_cast
this
to a pointer of a inherited struct B
. It is done twice: using normal and constant evaluations, and the result of both is printed.
#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;
}
With normal evaluation std::cout << B{}.x
everything is simple and 0
is printed, since in the constructor of A
the object cannot be cast to a child class.
But with constant evaluation the compilers diverge. Only Clang prints second 0
. MSVC already prints second 1
meaning that the result of dynamic_cast
was not nullptr
. And GCC prints vague error:
<source>:14:24: in 'constexpr' expansion of 'B()'
<source>:9:8: in 'constexpr' expansion of '((B*)this)->B::<anonymous>.A::A()'
<source>:14:24: error: '((&<anonymous>.B::<anonymous>) != 0)' is not a constant expression
14 | constexpr bool b = B{}.x;
Online demo: https://godbolt.org/z/xr8rdP93a
Is the program above well defined and if yes, what shall it print?
P.S. I think it is not a duplicate of two other questions:
because the main focus here is constant evaluation, which is not covered there at all.