2016-09-29 66 views
12

我發現一個問題,我猜是由於GCC中的一個錯誤。
無論如何,在開啓問題之前,我想確定一下。std :: list :: remove_if如果與普通的lambda結合使用會變得很瘋狂

考慮下面的代碼:

#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)預期。
GCC v6.2 compiles (1),但它是doesn't compile (2)
返回的錯誤是:

error: 'f' was not declared in this scope

而且,請注意,GCC compiles (2)如果因爲它遵循它修改:

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

據我所知,使用的const auto &代替const T &應該不會改變在這種情況下的行爲。

這是GCC的錯誤嗎?

+0

我想知道編譯器在什麼範圍內生成代表* generic * lambda的類:文件範圍,類範圍,函數範圍(作爲本地類,但不支持函數模板作爲成員)? – Nawaz

+0

From [here](http://eel.is/c++draft/expr.prim.lambda#4) - _閉包類型在包含相應lambda的最小塊範圍,類範圍或命名空間範圍中聲明-表達_。我會說'S ',這就是爲什麼我認爲這是一個錯誤,它應該看到'f'的聲明。 – skypjack

+1

@Nawaz可能[this](http://eel.is/c++draft/expr.prim.lambda#10)更合適 - 本地lambda表達式的擴展範圍是一系列封閉範圍幷包括最內部的封閉函數及其參數_? – 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中的錯誤。