Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::list::remove_if goes crazy if combined with a generic lambda

I found a problem that I guess is due to a bug in GCC.
Anyway, before opening an issue, I would like to be sure.

Consider the code below:

#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 compiles both (1) and (2) as expected.
GCC v6.2 compiles (1), but it doesn't compile (2).
The returned error is:

error: 'f' was not declared in this scope

Moreover, note that GCC compiles (2) if it is modified as it follows:

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

As far as I know, using an const auto & instead of const T & should not alter the behavior in this case.

Is it a bug of GCC?

like image 603
skypjack Avatar asked Sep 29 '16 09:09

skypjack


1 Answers

Per [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;

Hoisting the compound-statement to the context of the lambda-expression gives a clearly valid program:

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

So yes, this is a bug in gcc.

like image 83
ecatmur Avatar answered Oct 21 '22 22:10

ecatmur