私には小さなおもちゃプログラムがあります:
static int value = 0;
int function(int &value=value) {
return value;
}
int main() {
function();
}
G ++ 7.2でコンパイルする:
g ++ -std = c ++ 11 -Wall -Wextra test.cc -o test
問題ない。
Clang ++-3.9でコンパイルする:
clang ++-3.9 -std = c ++ 11 -Wall -Wextra test.cc -o test
test.cc:3:25: error: default argument references parameter 'value'
int function(int &value=value) {
^~~~~
test.cc:8:5: error: no matching function for call to 'function'
function();
^~~~~~~~
test.cc:3:5: note: candidate function not viable: requires single argument 'value', but no arguments were provided
int function(int &value=value) {
^
2 errors generated.
カボム。誰が正しい?
Clangは正しいと思います。 basic.scope.pdecl から:
以下の場合を除き、名前の宣言点は、完全な宣言子(Clause [dcl.decl] )の直後で、初期化子(ある場合)の前です。 [例:
int x = 12;{ int x = x; }
ここで、2番目のxは独自の(不定の)値で初期化されます。 —終了例]
また、 dcl.fct.default から:
デフォルトの引数は、関数が呼び出されるたびに評価されます。関数の引数の評価の順序は指定されていません。したがって、関数のパラメーターは、評価されていなくても、デフォルトの引数で使用されません。デフォルト引数の前に宣言された関数のパラメーターはスコープ内にあり、名前空間とクラスメンバー名を隠すことができます
OPは質問にc ++ 11というタグを付けたので、そのバージョンの標準を確認し、 [basic.lookup.unqual] sub-clause 11で明示的に次のように述べています。
関数parameter-declaration-clauseのデフォルト引数(8.3.6)として使用される名前、またはコンストラクター(12.6.2)のmem-initializerの式で使用される名前の検索中に、関数パラメーター名が表示され、関数宣言を含むブロック、クラス、または名前空間スコープで宣言されたエンティティの名前を非表示にします。
したがって、clangは正しいです。
Clangはここで正しいです。最初に 関数のパラメータースコープ は次のように定義されます:
関数パラメーター(ラムダ宣言子に現れるものを含む)または関数ローカルの事前定義変数([dcl.fct.def])には関数パラメーターのスコープがあります。パラメータまたは関数ローカルの事前定義変数の潜在的なスコープは、宣言のポイントから始まります。[...]
宣言のポイント は次のように定義されます
以下の場合を除き、名前の宣言点は、完全な宣言子の直後で、初期化子(存在する場合)の前です。 [例:
unsigned char x = 12; { unsigned char x = x; }
ここで、2番目のxは独自の(不定の)値で初期化されます。 —例を終了]
value
は、グローバルスペースからではなく、宣言したvalue
でなければなりません