4

以下のマークされた行が正常にコンパイルされる理由を誰かが説明してください:

template<typename T, int N>
constexpr
int get_size(T (&)[N])
{
    return N;
}

int main()
{
    int xs[10];
    constexpr int y = get_size(xs); // HERE.
    static_assert(10 == y, "wrong size");
}

私にとって直感的には、それ自体がget_size(xs)定数式でxsはないので、それが機能する理由がわかりません。

4

2 に答える 2

4

テンプレート関数がインスタンス化されると、プログラムは次のようになります。

constexpr
int get_size(int (&)[10])
{
    return 10;
}

int main()
{
    int xs[10];
    constexpr int y = get_size(xs); // HERE.
    static_assert(10 == y, "wrong size");
}

次に、関数呼び出し置換の後、次と同等になります。

int main()
{
    int xs[10];
    constexpr int y = 10; // HERE.
    static_assert(10 == y, "wrong size");
}

関数呼び出しの置換については、7.1.5 [dcl.constexpr]/5 で説明されています。基本的に、パラメーターは、コピー初期化された場合のように置換され、その後、戻り式の出現に置き換えられます。return 式は、同様に戻り値をコピー初期化します。結果の式は、関数呼び出しに代入される式になります。この後でのみ、コンテキストによって配置された定数式の制約を満たす場合にのみ、式が考慮されます。(もちろん、高品質のコンパイラは、そのような操作の後に constexpr 関数を正常に使用できず、関数定義に遭遇した後に失敗する可能性があると判断できますが、そうする必要はありません)

また、混乱を招くように、この概念は C++14 では削除され、constexpr 関数の評価方法に関する別の概念に置き換えられていることに注意してください。特に、if ステートメント、 for ステートメント、および constexpr 関数内のリテラル型のローカル変数を使用できます。

于 2013-10-16T12:57:37.590 に答える