Подтвердить что ты не робот

Тестирование endianess во время компиляции: эта функция constexpr правильна в соответствии со стандартом?

После некоторого поиска способа проверки endianess во время компиляции я придумал следующее решение:

static const int a{1};

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

GCC принимает этот код только в некоторых контекстах, где требуется constexpr:

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

Во втором случае GCC говорит error: accessing value of ‘a’ through a ‘char’ glvalue in a constant expression. Я не мог найти ничего в стандарте, который запрещает такую ​​вещь. Может быть, кто-то может прояснить, в каком случае GCC верен?

4b9b3361

Ответ 1

Это то, что я получаю от Clang 3.1 ToT:

error: функция constexpr никогда не создает константное выражение

§5.19 [expr.const]

p1 В некоторых контекстах требуются выражения, удовлетворяющие дополнительным требованиям, как подробно описано в этом подпункте; другие контексты имеют разную семантику в зависимости от того, удовлетворяет ли это выражение этим требованиям. Выражения, удовлетворяющие этим требованиям, называются константными выражениями.

p2 Условное выражение является выражением основной константы, если оно не включает одно из следующих значений в качестве потенциально оцениваемого подвыражения:

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

Итак, (char*)&(a) оценивается как reinterpret_cast, поэтому функция никогда не является действительной функцией constexpr.

Ответ 2

Вы должны изучить Boost.Detail.Endian

Это сопоставление нескольких архитектур с их контентом (через макросы BOOST_BIG_ENDIAN, BOOST_LITTLE_ENDIAN и BOOST_PDP_ENDIAN). Насколько я знаю, нет фактического способа определить континент во время компиляции, кроме списка, подобного этому.

Для примера реализации, использующей Boost.Detail.Endian, вы можете увидеть библиотеку, которую я надеюсь получить для отправки в Boost: https://bitbucket.org/davidstone/endian/ (соответствующий файл byte_order.hpp, но unsigned.hpp необходим, если вы хотите просто использовать мою реализацию).

Ответ 3

Если N3620 - преобразование заказа на сетевое байтовое число реализовано, вы сможете использовать constexpr ntoh для проверки подлинности, но помните, что существуют редкие архитектуры, такие как middle-endian, и вы никогда не сможете поддерживать все из них.