web-dev-qa-db-ja.com

constexpr参照を初期化する方法

constexpr参照を初期化しようとしていますが成功しません。私は試した

#include <iostream>

constexpr int& f(int& x) // can define functions returning constexpr references
{
    return x;
}

int main()
{
    constexpr int x{20};
    constexpr const int& z = x; // error here
}

しかし、コンパイル時のエラーが発生します

エラー:constexpr変数 'z'は定数式で初期化する必要があります

constを削除すると、

エラー:タイプ 'int'への参照をタイプ 'const int'の値にバインドすると、修飾子が削除されます

constexprは変数宣言に対して自動的にconstを意味するように感じましたが。

だから私の質問は:

  1. constexpr参照はこれまでに役立ちましたか? (つまり、const参照よりも「優れている」)
  2. はいの場合、どうすればそれらを効果的に定義できますか?

PS: どの値を `constexpr`参照に割り当てることができますか? など、私の質問に関連する質問をいくつか見ましたが、それらが私の質問に対応しているとは思いません。

22
vsoftco
  1. Constexprリファレンスはこれまでに役立ちましたか? (つまり、const参照よりも「優れている」)

これらはプログラムの開始前に初期化されることが保証されていますが、constへの参照は、プログラムの実行開始後の動的初期化中に初期化できます。

  1. はいの場合、どうすればそれらを効果的に定義できますか?

constexpr参照は、ローカル変数ではなくグローバル変数にバインドする必要があります(または、より正式には、静的ストレージ期間を持つものにバインドする必要があります)。

参照は、概念的には変数のアドレスを取得することと同等であり、ローカル変数のアドレスは定数ではありません(mainは1回しか呼び出せないため、ローカル変数は1回しか初期化されません)。

24
Jonathan Wakely

したがって、問題は、constexpr参照が静的ストレージ期間を持つオブジェクトにバインドする必要があることです。これは ドラフトC++ 11標準:N3337 セクション5.19[expr.const]emphasis mine):

参照定数式は、オブジェクトを指定する左辺値コア定数式です静的ストレージ期間付きまたは関数

ドラフトC++ 14標準:N3936 文言を変更します:

定数式は、値が静的ストレージ期間を持つオブジェクトまたは関数を参照するglvalueコア定数式、または値がオブジェクトであるprvalueコア定数式のいずれかです。このオブジェクトとそのサブオブジェクトの場合:

  • 参照型の各非静的データメンバーは、静的ストレージ期間を持つオブジェクトまたは関数を参照し、
  • オブジェクトまたはサブオブジェクトがポインター型の場合、静的ストレージ期間を持つオブジェクトのアドレス、そのようなオブジェクトの終わりを超えたアドレス(5.7)、関数のアドレス、またはnullポインター値が含まれます。

したがって、xの宣言をそのように変更すると機能します。

constexpr static int x{20};
9
Shafik Yaghmour

T.C。 が言うように、初期化子は静的な保存期間を持つオブジェクトである必要があります。

N4140 /§5.19/ 4A定数式は、値が静的ストレージ期間のオブジェクトを参照するglvalueコア定数式のいずれかです[...]

N4140 /§7.1.5/ 9オブジェクト宣言で使用されるconstexpr指定子は、オブジェクトをconstとして宣言します。このようなオブジェクトはリテラル型であり、初期化されます。 [...]それ以外の場合、またはconstexpr指定子が参照宣言で使用されている場合、その初期化子に表示されるすべての完全式は定数式でなければなりません。

N3337では、表現が異なります。

5
user3920237