Как отмечает Люк Дантон, ваши попытки блокируются правилами в [expr.const]/2, которые говорят, что различные выражения не допускаются в основной константе выражения, в том числе:
- в reinterpret_cast
- операция, которая будет иметь неопределенное поведение [Примечание: в том числе [...] некий указатель арифметической [...] - конец записки]
первая пуля исключает ваш первый пример. Второй пример исключается первой пули выше, плюс правило из [expr.cast]/4, что:
Преобразования выполняются [...] reinterpret_cast
[...] может быть выполнена используя буквенное обозначение преобразования явного типа. Используются те же смысловые ограничения и поведение.
Вторая пуля была добавлена WG21 core issue 1313, и уточняет, что арифметические операции над указателями на нулевой указатель не допускается в постоянном выражении. Это исключает ваш третий пример.
Даже если эти ограничения не относятся к основным константных выражений, он все равно будет невозможно инициализировать constexpr
указатель со значением полученного литьем целое, так как переменная указатель constexpr должен быть инициализируется константным выражением адреса, который, [expr.const]/3, должно быть оценено в
адрес объекта со статической продолжительностью хранения, адресом функции или значением нулевого указателя.
Целое число, отличное от типа указателя, не является ничем из этого.
g ++ еще не строго соблюдает эти правила, но его последние выпуски приближаются к ним, поэтому мы должны предположить, что он в конечном итоге полностью их реализует.
Если ваша цель - объявить переменную, для которой выполняется статическая инициализация, вы можете просто отказаться от constexpr
- и clang, и g ++ выдадут статический инициализатор для этого выражения. Если вам нужно это выражение быть частью константного выражения для какой-то причины, у вас есть два варианта:
- реструктурировать свой код так, что intptr_t передается вокруг вместо указателя, и привести его к типу указателя, когда вы необходимо (за пределами постоянного выражения) или
- Использовать
__builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF
. Эта точная форма выражения (с __builtin_constant_p
в левой части условного оператора) отключает проверку строгого постоянного выражения в объятиях условного оператора и мало известна, но documented, не переносимое расширение GNU, поддерживаемое и gcc и clang.
Зачем вам здесь constexpr? Не является ли constexpr эффективным тем же, что и const, если вы не используете функцию? –
@RobertMason: Ну, например, если это статический член класса и он не constexpr, я не могу инициализировать его в строке. – HighCommander4
Возможно, статическая встроенная функция-член будет более подходящей, чем элемент данных. –