Gcc std::list::如果与通用lambda组合会变得疯狂,则删除

Gcc std::list::如果与通用lambda组合会变得疯狂,则删除,gcc,lambda,clang,c++14,language-lawyer,Gcc,Lambda,Clang,C++14,Language Lawyer,我发现了一个问题,我猜是由于GCC中的一个错误造成的。 无论如何,在开始一个问题之前,我想确定一下 考虑以下代码: #include<algorithm> #include<list> template<typename U> struct S { using FT = void(*)(); struct T { FT func; }; template<typename> static void f() {

我发现了一个问题,我猜是由于GCC中的一个错误造成的。
无论如何,在开始一个问题之前,我想确定一下

考虑以下代码:

#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();
}
#按预期包含。
GCC v6.2,但它是 返回的错误为:

错误:未在此作用域中声明“f”

此外,请注意,如果GCC修改如下:

l.remove_if([](const auto &t) { return t.func == &S<U>::f<int>; }); // (2)
l.remove_if([](const auto&t){return t.func==&S::f;});//(2)
据我所知,在这种情况下,使用
const auto&
而不是
const T&
不应该改变行为


这是GCC的错误吗?

根据[expr.prim.lambda]

8-[…]出于名称查找的目的(3.4)[…]在lambda表达式的上下文中考虑复合语句。[……]

:

模板
结构{
模板静态void f();
S(){void(*g)(char)=[](auto){f;};}
};
S S;
将复合语句提升到lambda表达式的上下文中,可以得到一个明显有效的程序:

template<int>
struct S {
  template<int> static void f();
  S() { f<0>; }
};
S<0> s;
模板
结构{
模板静态void f();
S(){f;}
};
S S;

是的,这是gcc中的一个bug。

我想知道编译器在什么范围内生成表示通用lambda的类:文件范围、类范围、函数范围(作为本地类,但不支持函数模板作为成员)?From-闭包类型在最小的块范围、类范围中声明,或包含相应lambda表达式的命名空间范围。我会说
S
,这就是为什么我认为这是一个bug,它应该看到
f
@Nawaz的声明可能更合适-本地lambda表达式的到达范围是一组封闭范围,包括最里面的封闭函数及其参数?如果删除外部模板,则@skypjack hmm(
typename
)它也会被编译…@W.F.是的,当然,我注意到了。这个最小的、有效的示例实际上是一个最小的示例!!我尽了最大努力。;-)
template<int>
struct S {
  template<int> static void f();
  S() { f<0>; }
};
S<0> s;