次のプログラムは、gcc 4.8.1 でエラーや警告なしにコンパイルされます
-Wall -std=c++11
。
template<unsigned N>
struct A{};
int main(){
A<1-2> a;
(void)a;
return 0;
}
同じオプションで clang 3.3 を実行すると、次のエラーが発生します。
エラー: 非型のテンプレート引数が -1 に評価され、型 'unsigned int' [-Wc++11-narrowing] に狭められません
この質問によると、標準がエラーを示し、clang が示されたエラーを示す場所で、変換を狭めるために警告を出すだけの gcc の現在のポリシーのように見えます。しかし、この場合、gcc は警告すら出ません。
§ 8.5.4/7 で標準によって与えられている縮小変換エラーの例 (その質問で再現) のいずれも、非型テンプレート引数の縮小変換のケースをカバーしていませんが、§ 14.3.2/5 では規格は次のように述べています。
整数型または列挙型の非型テンプレート パラメータの場合、変換された定数式 (5.19) で許可されている変換が適用されます。
§ 5.19/3 には次のように書かれています。
型 T の変換された定数式は、リテラル定数式であり、暗黙的に型 T に変換されます。暗黙的な変換 (存在する場合) はリテラル定数式で許可され、暗黙的な変換シーケンスには、ユーザー定義の変換 (左辺値から左辺値への変換) のみが含まれます。縮小変換(8.5.4)以外の右辺値変換 (4.1)、整数昇格 (4.5)、および整数変換 (4.7 )
(私の強調)。
これは、この場合、gcc 自体の尺度でさえ、縮小変換をまったく診断しないという点で誤りがあることを意味しているように私には思えます。私はこれを正しく読んでいますか?標準ベースの反論はありますか?
単なる好奇心よりも気持ちを込めて質問しています。再帰的な TMP 設定では、この場合の clang のエラー診断は、符号なしの非型テンプレート引数が 0 を通過するバグを特定しますが、gcc から得られるのは「テンプレートのインスタンス化の最大深度を超えました」だけです。