Подтвердить что ты не робот

Std:: list:: remove_if сходит с ума, если в сочетании с общей лямбдой

Я нашел проблему, которая, я думаю, связана с ошибкой в ​​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();
}

clang v3.9 компилирует как (1), так и (2), как ожидалось.
GCC v6.2 компилирует (1), но не компилируется ( 2).
Возвращенная ошибка:

error: 'f' не был объявлен в этой области

Кроме того, обратите внимание, что GCC компилирует (2), если он изменен следующим образом:

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

Насколько я знаю, использование const auto & вместо const T & не должно изменять поведение в этом случае.

Является ли это ошибкой GCC?

4b9b3361

Ответ 1

Per [expr.prim.lambda]:

8 - [...] [Для] целей поиска имени (3.4) [...] составной оператор рассматривается в контексте лямбда-выражения. [...]

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.