2017-04-20 38 views
3
#include <iostream> 

using namespace std; 

template<const int arr[]> 
struct S { 
    static constexpr int value = arr[0]; 
}; 

constexpr int arr[] = { 5 }; 

int main() { 
    cout << S<arr>::value << endl; 
} 

としてconstexprのアレイを使用してこのプログラムは、GCC 5.1以降で5微細かつプリントをコンパイルするが、MSVC 19.10.25019は、次のエラーを与える:テンプレート非型引数(C++ 14)

エラーC2975:「S」:「ARR」の無効なテンプレート引数は、 コンパイル時の定数式エラーC2131を期待:式が が一定

に評価されなかったによると、このプログラム有効ですC++ 14標準、またはgccはここであまりにも寛容ですか?

+0

についてレコードでは、Clangもこのコードを受け入れます。 – jwimberley

+0

'arr []'を 'arr [1]'に置き換えた場合、MSVCは何を言いますか? – jwimberley

+0

@jwimberley何も変わりません。 –

答えて

2

私の見ている限り、プログラムは整形式です。

[temp.param]/8によれば、テンプレートパラメータは実際にはconst int*であり、const int[]ではありません。

タイプの非タイプテンプレートパラメータTのアレイ」または「Tを返す関数」は、それぞれ、タイプ 「Tへのポインタ」または「Tを返す関数へのポインタ」となるように調整されます。

[temp.arg.nontype]/1によれば、我々は、テンプレートパラメータの引数として静的記憶域期間と外部結合を持つ完全な配列オブジェクトの名前を使用することができます。

を - constの

...

:非タイプ、非テンプレートテンプレート・パラメータのテンプレート引数は、のいずれかでなければなりません静的記憶時間と外部または内部リンケージを持つ完全なオブジェクトのアドレスを指定するant式(5.19)、関数を含む外部または内部リンケージを持つ関数 テンプレートと関数template-idsただし、非静的クラスメンバは除きます。 ID発現名前が関数または配列を意味し、省略されなければならない場合 &が省略されてもよいことを除いて、オブジェクトまたは関数の名前である&ID発現、として(括弧を無視する)を発現対応する場合 テンプレートパラメータを参照してください...

arrは、MSVCがそうではないと考えるにもかかわらず、定数式です。これは、禁止された評価を含まないため、静的記憶期間([expr.const]/4)を持つオブジェクトを指しているので、[expr.const]/2に従うコア定数式です。

テンプレートパラメータは静的記憶期間を持つ配列を参照するため、テンプレートのインスタンス化時に配列の境界がわかります。したがって、arr[0]へのアクセスが正式なコア定数式であることを検証することができます。これは、明確な動作を持ち、[expr。CONST]/2:

... と不揮発性のconstオブジェクトに先行する初期化を指す一体または列挙タイプの不揮発性glvalue、定数式で初期化

+0

技術的には、[temp.arg.nontype] /2.1に違反します: "...ポインタ型の非型テンプレートパラメータの場合、定数式の値は... ...のアドレスにはなりませんサブオブジェクト "となる。ポインタは、サブオブジェクトである配列の最初の要素を指します。しかし、それは現在の言葉遣いに関する既知の問題です。 CWG 2043を参照のこと。 –

関連する問題