TL; DR
clang
верен, это известно gcc
. Вы можете использовать intptr_t
вместо этого и использовать, когда вам нужно использовать это значение, или если это не работает, то оба gcc
и clang
поддерживают небольшую задокументированную работу, которая должна разрешить ваш конкретный вариант использования.
Подробности
Итак, clang
верна на этом, если мы перейдем к черновому стандарту C ++ 11 5.19
Константные выражения paragraph 2 говорит:
Условное выражение является выражением постоянной константы, если оно не включает одно из следующих значений как потенциально оцененное subexpression [...]
blockquote>и включает следующую марку:
- reinterpret_cast (5.2.10);
blockquote>Одним простым решением было бы использовать intptr_t :
static constexpr intptr_t ptr = 0x1;
, а затем использовать позже, когда вам нужно его использовать:
reinterpret_cast
(foo::ptr) ; Возможно, соблазнительно оставить это, но эта история становится интереснее. Это известно и все еще открывает ошибку
gcc
, см. Ошибка 49171: [C ++ 0x] [constexpr] Константные выражения поддерживают reinterpret_cast . Из обсуждения видно, что у разработчиковgcc
есть некоторые явные примеры использования:Я считаю, что нашел подходящее использование reinterpret_cast в постоянных выражениях, используемых в C ++ 03:
//---------------- struct X { X* operator&(); }; X x[2]; const bool p = (reinterpret_cast
(&reinterpret_cast (x[1])) - reinterpret_cast (&reinterpret_cast (x[0]))) == sizeof(X); enum E { e = p }; // e should have a value equal to 1 //---------------- В основном эта программа демонстрирует технику, на основе функции библиотеки адресов C ++ 11 на основе и, исключая reinterpret_cast безоговорочно из постоянных выражений на базовом языке, эта полезная программа недействителен и сделает невозможным объявление addressof как функции constexpr.
blockquote>, но не смог получить исключение, вырезанное для этих случаев использования, см. закрытые вопросы 1384 :
Хотя reinterpret_cast разрешен в выражениях константы адреса в C ++ 03, это ограничение было реализовано в некоторых компиляторах и не доказало, что оно нарушает значительные количества кода. CWG посчитал, что осложнения, связанные с указателями, чьи изменения изменились (арифметика указателя и разыменование не могли быть разрешены на таких указателях), перевешивали возможную полезность ослабления ограничения тока.
blockquote>НО , по-видимому,
gcc
иclang
поддерживают небольшое документированное расширение, которое позволяет постоянно складывать непостоянные выражения, используя __ builtin_constant_p (exp) , и поэтому следующие выражения принимаются какgcc
иclang
:static constexpr const void* ptr = __builtin_constant_p( reinterpret_cast
(0x1) ) ? reinterpret_cast (0x1) : reinterpret_cast (0x1) ; Поиск документации для этого почти невозможно, но это llvm commit является информативным со следующими фрагментами, которые содержат интересное чтение:
blockquote>
- поддерживает gcc __builtin_constant_p ()? ...: ... складной взлом в C ++ 11
и:
+ // __builtin_constant_p? : является магическим и всегда является потенциальной константой.
blockquote>и:
blockquote>
- // Этот макрос заставляет свой аргумент быть сложенным, даже если это не
- // иначе константное выражение.
определяет fold (x) (__builtin_constant_p (x)? (x): (x))
Мы можем найти более формальное объяснение этой функции в электронной почте gcc-patches: C постоянные выражения, VLA и т. д. исправления , который гласит: :
Кроме того, правила для __builtin_constant_p, вызываемые как условие условного выражения в реализации, более расслаблены, чем правила в формальной модели: выбранная половина условного выражения полностью свернута без учета того, формально является постоянным выражением, поскольку __builtin_constant_p проверяет полностью сложенный аргумент.
blockquote>