Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing endianess at compile-time: is this constexpr function correct according to the standard?

After some search for a way to check endianess at compile-time I've come up with the following solution:

static const int a{1};

constexpr bool is_big_endian()
{
    return *((char*)&(a)) == 1;
}

GCC accepts this code only in some contexts where constexpr is required:

int b[is_big_endian() ? 12 : 25]; //works
std::array<int, testendian() ? 12 : 25> c;  //fails

For the second case, GCC says error: accessing value of ‘a’ through a ‘char’ glvalue in a constant expression. I couldn't find anything in the standard that forbids such thing. Maybe someone could clarify in which case GCC is correct?

like image 456
p12 Avatar asked Feb 05 '12 20:02

p12


People also ask

Is constexpr evaluated at compile time?

A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.

Does constexpr improve performance?

Using constexpr to Improve Security, Performance and Encapsulation in C++ constexpr is a new C++11 keyword that rids you of the need to create macros and hardcoded literals. It also guarantees, under certain conditions, that objects undergo static initialization.

Is constexpr evaluated?

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.


2 Answers

This is what I get from Clang 3.1 ToT:

error: constexpr function never produces a constant expression

§5.19 [expr.const]

p1 Certain contexts require expressions that satisfy additional requirements as detailed in this sub-clause; other contexts have different semantics depending on whether or not an expression satisfies these requirements. Expressions that satisfy these requirements are called constant expressions.

p2 A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression:

  • [...]
  • a reinterpret_cast (5.2.10);

So, (char*)&(a) evaluates to a reinterpret_cast, as such the function is never a valid constexpr function.

like image 99
Xeo Avatar answered Oct 05 '22 23:10

Xeo


You should look into Boost.Detail.Endian

It is a mapping of several architectures to their endianness (through the macros BOOST_BIG_ENDIAN, BOOST_LITTLE_ENDIAN, and BOOST_PDP_ENDIAN). As far as I know, there is no actual way to determine the endianness at compile time, other than a list like this.

For an example implementation that uses Boost.Detail.Endian, you can see the library I'm hoping to get reviewed for submission to Boost: https://bitbucket.org/davidstone/endian/ (the relevant file is byte_order.hpp, but unsigned.hpp is necessary as well if you want to just use my implementation).

like image 33
David Stone Avatar answered Oct 05 '22 23:10

David Stone