2011-12-29 19 views
9

これは、問題を再現することができる最も簡単な例です。静的ローカル変数への未定義の参照

template<class T> 
struct X 
{ 
    static void foo() 
    { 
     static int z = 0; 
     []{ z = 1; }(); 
    } 
}; 

int main() 
{ 
    X<int>::foo(); 
    return 0; 
} 

私がg ++ 4.6は、Ubuntuの中でも、MinGWの4.6と4.7でそれを試してみたし、それらのすべては、私のリンクエラー「`Z 'への未定義の参照」を与えます。だから、これは私がこれが法的であるかどうか疑問に思います。 VC10は問題ありません。

Xがテンプレートの代わりに通常のクラスであれば動作します。また、ラムダをローカルクラスに置き換えてもエラーが発生するので、ラムダとは関係ないと思います。以下を受け入れたが、VC++はない++

+0

C++ 11タグを追加すると、より良い応答が得られるかもしれません。 – marcinj

答えて

10

G:ここz

[&z]{ z = 1; }(); 

がそのようにG ++ 未定義参照文句ない捕捉されています。しかし:

5.1.2/10:

非修飾名ルックアップ(3.4.1)のための通常の規則を使用して検索されているキャプチャー・リスト内の識別子。それぞれのルックアップは、 ローカルラムダ式の範囲 に到達すると自動的に格納される変数を見つけます。

zない自動ストレージです。したがって、zをキャプチャすることはできません。したがって、g ++の動作は正しくなく、VC++は正しいです。

[]{ z = 1; }(); 

zラムダ本体に許容されるVC++などの静的記憶装置、によってアクセスされる:VC++を受け入れてない++ Gがそのコードに

、 g ++は明らかに上記で宣言された静的変数にzという名前を解決しないので、定義されていない参照をにスローします。

TL; DR それは

++おそらく編集グラムのバグです: It is indeed a bugと4.7に固定されています。

+0

ニース: "zへの参照"が自動ストレージを持つかどうかはわかりませんが、TonyKの実際の作業が実際に動作する理由について説明します。 5.2.1/9を参照すると、あなたのノートが参照する「到達範囲」は最も内側にある関数で停止するので、「グローバル」(自動的に保存期間がない)も除外されます。したがって、キャプチャリストはコピーによってローカル変数のみを取得することが完全に意図されているようです。 –

-1

なぜそれがテンプレートではなく通常のクラスで動作するのか分かりません。あなたが参照することにより、ローカル変数zをキャプチャする場合しかし、あなたはあなたの例では、仕事を得ることができます:

static void foo() 
{ 
    static int z = 0; 
    [&z]{ z = 1; }(); // Note: [&z] 
} 

ウィキペディア詳細hereを持っています。

+0

@cicadaという名前の誰かが同じ回答を投稿しましたが、削除しました(今は同じ回答でここにいます)。なぜそれが削除されたのか分かりません。0_0 –

+0

@ Mr.Anubis g ++はVC++とは異なる振る舞いをします。 –

+0

@Cicadaどちらのコンパイラでもバグがあっても別のものでも動作は自由です。 –

関連する問題