c++ - constexpr and initialization of a static const void pointer with reinterpret cast, which compiler is right? -
c++ - constexpr and initialization of a static const void pointer with reinterpret cast, which compiler is right? -
consider next piece of code:
struct foo { static constexpr const void* ptr = reinterpret_cast<const void*>(0x1); }; auto main() -> int { homecoming 0; }
the above illustration compiles fine in g++ v4.9 (live demo), while fails compile in clang v3.4 (live demo) , generates next error:
error: constexpr variable 'ptr' must initialized constant expression
questions:
which of 2 compilers right according standard?
what's proper way of declaring look of such kind?
tl;dr
clang
correct, known gcc
bug. can either utilize intptr_t
instead , cast when need utilize value or if not workable both gcc
, clang
back upwards little documented work-around should allow particular utilize case.
details
so clang
right on 1 if go draft c++11 standard section 5.19
constant expressions paragraph 2 says:
a conditional-expression core constant look unless involves 1 of next potentially evaluated subexpression [...]
and includes next bullet:
— reinterpret_cast (5.2.10);
one simple solution utilize intptr_t:
static constexpr intptr_t ptr = 0x1;
and cast later on when need utilize it:
reinterpret_cast<void*>(foo::ptr) ;
it may tempting leave @ story gets more interesting though. know , still open gcc
bug see bug 49171: [c++0x][constexpr] constant expressions back upwards reinterpret_cast. clear give-and-take gcc
devs have clear utilize cases this:
i believe found conforming usage of reinterpret_cast in constant expressions useable in c++03:
//---------------- struct x { x* operator&(); }; x x[2]; const bool p = (reinterpret_cast<x*>(&reinterpret_cast<char&>(x[1])) - reinterpret_cast<x*>(&reinterpret_cast<char&>(x[0]))) == sizeof(x); enum e { e = p }; // e should have value equal 1 //----------------
basically programme demonstrates technique, c++11 library function addressof based on , excluding reinterpret_cast unconditionally constant expressions in core language render useful programme invalid , create impossible declare addressof constexpr function.
but not able exception carved these utilize cases, see closed issues 1384:
although reinterpret_cast permitted in address constant expressions in c++03, restriction has been implemented in compilers , has not proved break important amounts of code. cwg deemed complications of dealing pointers tpes changed (pointer arithmetic , dereference not permitted on such pointers) outweighed possible utility of relaxing current restriction.
but apparently gcc
, clang
back upwards little documented extension allows constant folding of non-constant expressions using __builtin_constant_p (exp) , next expressions accepted both gcc
, clang
:
static constexpr const void* ptr = __builtin_constant_p( reinterpret_cast<const void*>(0x1) ) ? reinterpret_cast<const void*>(0x1) : reinterpret_cast<const void*>(0x1) ;
finding documentation near impossible llvm commit informative next snippets provide interesting reading:
support gcc __builtin_constant_p() ? ... : ... folding hack in c++11and:
+// __builtin_constant_p ? : magical, , potential constant.
and:
// macro forces argument constant-folded, if it's not // otherwise constant expression. define fold(x) (__builtin_constant_p(x) ? (x) : (x))we can find more formal explanation of feature in gcc-patches email: c constant expressions, vlas etc. fixes says:
furthermore, rules __builtin_constant_p calls conditional look status in implementation more relaxed in formal model: selected half of conditional look folded without regard whether formally constant expression, since __builtin_constant_p tests folded argument itself.
c++ gcc c++11 clang constexpr
Comments
Post a Comment