Эндианность в constexpr

Я хочу создать функцию constexpr, которая возвращает континент системы, например:

constexpr bool IsBigEndian()
{
    constexpr int32_t one = 1;
    return (reinterpret_cast<const int8_t&>(one) == 0);
}

Теперь, поскольку функция будет выполняться во время компиляции, а не на реальной целевой машине, какая гарантия дает спецификация С++, чтобы убедиться, что верный результат возвращается?

Ответ 1

Отсутствует. На самом деле программа плохо сформирована. Из [expr.const]:

Условное выражение e является выражением постоянной константы, если оценка e, следуя правилам абстрактная машина (1.9), оценила бы одно из следующих выражений:
 - [...]
 - a reinterpret_cast.
 - [...]

И, из [dcl.constexpr]:

Для функции constexpr или конструктора constexpr, который не является ни дефолтом, ни шаблоном, если нет аргумента существуют такие значения, что вызов функции или конструктора может быть оцененным подвыражением основное постоянное выражение (5.20), или, для конструктора, постоянный инициализатор для некоторого объекта (3.6.2), программа плохо сформирована; не требуется диагностика.


Способ сделать это - просто надеяться, что ваш компилятор достаточно хорош, чтобы предоставить макросы для подтверждения вашей машины. Например, в gcc я мог бы использовать __BYTE_ORDER__:

constexpr bool IsBigEndian() {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    return false;
#else
    return true;
#endif
}

Ответ 2

Как заявил Барри, ваш код не является законным С++. Однако, даже если вы забрали часть constexpr, это все равно не будет законным С++. Ваш код нарушает строгие правила псевдонимов и, следовательно, представляет поведение undefined.

В самом деле, в С++ нет возможности обнаружить конечную цель объекта без вызова поведения undefined. Отключение его до char* не работает, потому что стандарт не требует большого или небольшого порядкового номера. Поэтому, пока вы можете читать данные через байт, вы не сможете юридически вывести что-либо из этого значения.

И тип punning через union терпит неудачу, потому что вам не разрешено вводить каламбур через union на С++ вообще. И даже если вы это сделали... снова, С++ не ограничивает реализацию большим или небольшим порядком.

Итак, что касается С++ в качестве стандарта, нет способа обнаружить это, будь то во время компиляции или времени выполнения.