I came across a problem with g++ with upcasting of a member pointer in a constexpr context using static_cast. See code example.
When compiling with g++ version 6.3 and 7.0 they give a compilation error saying reinterpret_cast is not a constant expression. While clang version 4.0 gives no error, which I think is correct since there is no reinterpret_cast here.
Is this a bug in g++ or clang? What is the correct behavior?
struct Base {};
struct Derived : Base
{
int i;
};
struct Ptr
{
constexpr Ptr(int Derived::* p) : p(static_cast<int Base::*>(p)){}
int Base::* p;
};
constexpr Ptr constexpr_ptr(&Derived::i);
Compiler output
g++ -c -std=c++14 test.cpp
test.cpp:17:40: in constexpr expansion of ‘Ptr(&Derived::i)’
test.cpp:11:41: error: a reinterpret_cast is not a constant expression
constexpr Ptr(int Derived::* p) : p(static_cast<int Base::*>(p)){}
^~~~~~~~~~~~~~~~~~~~~~~~~~~
GCC presumably misapprehends [expr.static.cast]/12, which permits your cast and notes that
If class
B
contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the behavior is undefined.
Since Base
is indeed a base of the class containing the member, the behaviour should be defined, and the constructor call a constant expression.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With