2016-09-29 3 views
12

GCCのバグが原因だと思う問題が見つかりました。
とにかく、問題を開く前に、私は確信しています。予想通りstd :: list :: remove_ifが一般的なラムダと組み合わされて狂ってしまう

#include<algorithm> 
#include<list> 

template<typename U> 
struct S { 
    using FT = void(*)(); 
    struct T { FT func; }; 

    template<typename> 
    static void f() { } 

    std::list<T> l{ { &f<int> }, { &f<char> } }; 

    void run() { 
     l.remove_if([](const T &t) { return t.func == &f<int>; }); // (1) 
     l.remove_if([](const auto &t) { return t.func == &f<int>; }); // (2) 
    } 
}; 

int main() { 
    S<void> s; 
    s.run(); 
} 

打ち鳴らすのV3.9 compiles both (1) and (2)

は、以下のコードを検討してください。
GCCv6.2 compiles (1)ですが、doesn't compile (2)です。
返されるエラーは、次のとおり

l.remove_if([](const auto &t) { return t.func == &S<U>::f<int>; }); // (2) 

を私の知る限り、変えるべきではないconst auto &代わりconst T &の使用:

error: 'f' was not declared in this scope

また、それは次のようにGCC compiles (2)は、それが変更された場合注意しますこの場合の動作

GCCのバグですか?

+0

コンパイラが* generic * lambda:file-scope、class-scope、function-scopeを表すクラスを生成するのは不思議です(local-classとして* )? – Nawaz

+0

ここから(http://eel.is/c++draft/expr.prim.lambda##) - _クロージャタイプは、対応するラムダを含む最小のブロックスコープ、クラススコープ、または名前空間スコープで宣言されています-expression_。私は 'S 'と言うでしょう。だからこそバグだと思うし、 'f'の宣言をするべきです。 – skypjack

+1

@Nawazおそらく[this](http://eel.is/c++draft/expr.prim.lambda#10)がさらに適切です - ローカルのラムダ式の到達範囲は、最大の囲みスコープのセットです最も内側の包囲関数とそのパラメータを含む。 – skypjack

答えて

8

[expr.prim.lambda]パー:

8 - [...] [For] purposes of name lookup (3.4) [...] the compound-statement is considered in the context of the lambda-expression. [...]

MCVE

template<int> 
struct S { 
    template<int> static void f(); 
    S() { void(*g)(char) = [](auto) { f<0>; }; } 
}; 
S<0> s; 

ラムダ式のコンテキストに化合物-文を巻き上げは明らかに有効なプログラムを提供します:

template<int> 
struct S { 
    template<int> static void f(); 
    S() { f<0>; } 
}; 
S<0> s; 

はい、これはgccのバグ。

関連する問題