Luc Danton が指摘しているように、あなたの試みは [expr.const]/2 のルールによってブロックされます。これは、次のようなさまざまな式がコア定数式で許可されていないことを示しています。
-- a reinterpret_cast
-- 未定義の動作をする操作 [注: [...] 特定のポインタ演算を含む [...] -- 終わりの注]
最初の箇条書きは、最初の例を除外します。2 番目の例は、上記の最初の箇条書きに加えて、[expr.cast]/4 の次のルールによって除外されます。
[...] a reinterpret_cast
[...] によって実行される変換は、明示的な型変換のキャスト表記を使用して実行できます。同じ意味上の制限と動作が適用されます。
2 番目の箇条書きはWG21 コアの問題 1313によって追加され、null ポインターでのポインター演算は定数式では許可されないことを明確にしています。これにより、3 番目の例が除外されます。
これらの制限がコア定数式に適用されなかったとしても、constexpr ポインター変数はアドレス定数式constexpr
によって初期化する必要があるため、整数をキャストすることによって生成された値でポインターを初期化することはできません。 .const]/3、次のように評価する必要があります
静的ストレージ期間を持つオブジェクトのアドレス、関数のアドレス、または null ポインター値。
ポインター型への整数キャストは、これらのいずれにも当てはまりません。
g++ はまだこれらの規則を厳密に適用していませんが、最近のリリースでは規則に近づいているため、最終的には完全に実装されると想定する必要があります。
静的初期化が実行される変数を宣言することが目標である場合は、単純にドロップできますconstexpr
-- clang と g++ の両方が、この式の静的初期化子を発行します。何らかの理由でこの式を定数式の一部にする必要がある場合は、次の 2 つの選択肢があります。
- ポインターの代わりに intptr_t が渡されるようにコードを再構築し、必要に応じて (定数式の外で) ポインター型にキャストするか、または
- を使用し
__builtin_constant_p((int*)0xFF) ? (int*)0xFF : (int*)0xFF
ます。この正確な形式の式 (__builtin_constant_p
条件演算子の左側にある) は、条件演算子のアームでの厳密な定数式チェックを無効にし、あまり知られていませんが、文書化された移植性のない GNU 拡張であり、両方でサポートされています。 gccとclang。