Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static_cast of member pointer in constexpr context on g++

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)){}
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
like image 314
jo-art Avatar asked Oct 18 '17 20:10

jo-art


1 Answers

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.

like image 151
Columbo Avatar answered Nov 19 '22 00:11

Columbo