【问题标题】:std::list::remove_if goes crazy if combined with a generic lambda如果与通用 lambda 结合,std::list::remove_if 会发疯
【发布时间】:2017-02-07 13:16:30
【问题描述】:

我发现了一个问题,我猜是由于 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 compiles both (1) and (2) 符合预期。
GCC v6.2 compiles (1),但它是 doesn't compile (2)
返回的错误是:

错误:'f' 未在此范围内声明

另外,注意GCC compiles (2)如果修改如下:

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

据我所知,使用 const auto &amp; 代替 const T &amp; 不应改变这种情况下的行为。

是不是 GCC 的 bug?

【问题讨论】:

  • 我想知道编译器在什么范围内生成代表 generic lambda 的类:文件范围、类范围、函数范围(作为本地类,但支持函数模板作为成员)?
  • 来自here - 闭包类型在包含相应lambda表达式的最小块作用域、类作用域或命名空间作用域中声明。我会说S&lt;U&gt;,这就是为什么我认为这是一个错误,它应该查看f的声明。
  • @Nawaz 也许this 更合适 - 本地 lambda 表达式的到达范围是一组封闭范围,包括最里面的封闭函数及其参数?
  • @skypjack 嗯,如果您删除外部模板 (typename &lt;class U&gt;),它也会被编译...
  • @W.F.是的,当然,我注意到了。最小的工作示例真的是 minimal 一个!我尽力了。 ;-)

标签: gcc lambda clang c++14 language-lawyer


【解决方案1】:

[expr.prim.lambda]

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

MCVE:

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

将复合语句提升到 lambda 表达式的上下文给出了一个明显有效的程序:

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

是的,这是 gcc 中的一个错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 2022-11-23
    • 2015-04-20
    相关资源
    最近更新 更多