Is constexpr accessing a member of a base class from an intermediate reference to the source class?

struct root { int i = 0; }; struct base: root{}; struct derive: base{}; constexpr derive d0; int main() { constexpr auto& r = static_cast<root const&>(d0); constexpr auto& b = static_cast<base const&>(r); constexpr auto& d = static_cast<derive const&>(r); static_assert(d0.i == 0, ""); // ok static_assert(ri == 0, ""); // ok static_assert(bi == 0, ""); // error in gcc static_assert(di == 0, ""); // ok } 

Clang accepts the code above, but gcc 7.2.0 compiles with the error below:

 prog.cc:17:5: error: non-constant condition for static assertion static_assert(bi == 0, ""); ^~~~~~~~~~~~~ prog.cc:17:5: error: accessing value of 'd.derive::<anonymous>.base::<anonymous>' through a 'const base' glvalue in a constant 

This is not constexpr, only if I get the value of 'i' through an intermediate base. Which compiler is right?

+7
c ++ constexpr
source share
1 answer

static_cast from the base class to the derived class is UB, as is static_cast between custom layout classes (those that have virtual or non-public members or bases or multiple inheritance). So that the code above is correct, you need public inheritance

 struct base : public root{}; struct derive : public base{}; 

and you can only static_cast from derive to base or root , and from base to root , and not in the other direction.

Given the usual GCC semantics, it probably "should" accept your code, but it also makes sense that this does not happen because it relies on non-standard behavior.

-2
source share

All Articles