注:C++ 17では、variables as inlineを宣言できます。
TL; DR:あなたは(非常に)安全側になりたい場合は、constexprの機能を持って行きます。しかし、これらのオブジェクトに対して簡単な操作を行い、その価値にのみ関心がある場合や、以下に示す危険なシナリオでは使用しない場合は、本質的に必要ではありません。
根本的な問題は、あなたのような名前空間のスコープの変数が内部リンケージ([basic.link]/(3.2))を持っているということです。これは、対応するヘッダーをコンパイルする各翻訳単位が異なるエンティティ(つまりシンボル)を観察することを意味します。
ここで、これらのオブジェクトを使用しているヘッダーにテンプレートまたはインライン関数があるとします。 ODRは、このシナリオについて非常に正確である - [basic.def.odr]/6:私たちはconstexpr
を話しているので、
「定数式で初期化は、」確かに、満たされています。だから"あなたはサルについては、D
"のすべての定義でオブジェクトが同じ値を持っています。
"オブジェクトはodr-usedではありません"はおそらく疑わしい条件です。基本的に、それはあなたが順番に
第ルールの唯一の例外
は、二つの上記のルールが得glvalueために違反していない限り、添字操作内部暗黙のアドレスを取ることができる配列です。
名潜在的に評価された式ex
がex
でODR-使用されているとして表示され、変数x
左辺値ツー右辺値の変換を適用しない限り:より正確には、ODR-使用が[basic.def.odr]/3によって支配され
(4.1)〜x
は、非自明な関数を呼び出さない定数式(5.20)を生成し、x
がオブジェクトである場合、の潜在的結果のセットの要素です。ここで、左辺 - 数値変換(4.1)はに適用されますまたはe
は、破棄された値の式です(句 5)。
任意のconstexpr
にl-t-rを適用すると、最初の部分の必要に応じて動作します。 2番目の部分は、実際のオブジェクトではなく、値として変数を使用する必要があります。つまり、最終的に破棄されるか直接評価され、上記の経験則が与えられます。
インライン関数やテンプレートなどの内部で変数のodr-useを使用しないようにすると、問題ありません。しかし、対応するconstexpr関数の戻り値を使用すると、prvaluesはすでに値/リテラル(オブジェクトではない)のように動作しており、constexpr関数はインラインであり、ODRに違反しないので心配する必要はありません(ifそこにはconstexpr
変数を使用しないでください!)。
名前空間スコープの定数には内部結合があります。この問題は 'inline'関数でそのような定数を評価するときに発生します。 –
あなたはどのプラットフォームにいますか? –
@ JohnB: 'constexpr char const * const kHello =" Hello ";'代わりに - + 11では 'constexpr'は' const'を意味しますが、C++では14 。 ODRがこの問題のC++ 14と大きく異なるのかどうかはわかりませんが、とにかく私の経験ではこれについてコンパイラの警告を得ることができます。 –