web-dev-qa-db-ja.com

この動作についてgccまたはclangは正しいですか?

私には小さなおもちゃプログラムがあります:

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.

カボム。誰が正しい?

38
gct

Clangは正しいと思います。 basic.scope.pdecl から:

以下の場合を除き、名前の宣言点は、完全な宣言子(Clause [dcl.decl] )の直後で、初期化子(ある場合)の前です。 [例:

int x = 12;{ int x = x; }

ここで、2番目のxは独自の(不定の)値で初期化されます。 —終了例]

また、 dcl.fct.default から:

デフォルトの引数は、関数が呼び出されるたびに評価されます。関数の引数の評価の順序は指定されていません。したがって、関数のパラメーターは、評価されていなくても、デフォルトの引数で使用されません。デフォルト引数の前に宣言された関数のパラメーターはスコープ内にあり、名前空間とクラスメンバー名を隠すことができます

32
R Sahu

OPは質問にc ++ 11というタグを付けたので、そのバージョンの標準を確認し、 [basic.lookup.unqual] sub-clause 11で明示的に次のように述べています。

関数parameter-declaration-clauseのデフォルト引数(8.3.6)として使用される名前、またはコンストラクター(12.6.2)のmem-initializerの式で使用される名前の検索中に、関数パラメーター名が表示され、関数宣言を含むブロック、クラス、または名前空間スコープで宣言されたエンティティの名前を非表示にします。

したがって、clangは正しいです。

18
Johan

Clangはここで正しいです。最初に 関数のパラメータースコープ は次のように定義されます:

関数パラメーター(ラムダ宣言子に現れるものを含む)または関数ローカルの事前定義変数([dcl.fct.def])には関数パラメーターのスコープがあります。パラメータまたは関数ローカルの事前定義変数の潜在的なスコープは、宣言のポイントから始まります。[...]

宣言のポイント は次のように定義されます

以下の場合を除き、名前の宣言点は、完全な宣言子の直後で、初期化子(存在する場合)の前です。 [例:

unsigned char x = 12;
{ unsigned char x = x; }

ここで、2番目のxは独自の(不定の)値で初期化されます。 —例を終了]

valueは、グローバルスペースからではなく、宣言したvalueでなければなりません

8
NathanOliver