在lambda中调用函数时ADL失败

时间:2017-12-03 16:42:00

标签: c++

我正在尝试从lambda调用一个函数,该函数是在特定成员函数中运行std :: for_each的一部分。 这里的例子: https://godbolt.org/g/KCBLjL

namespace A {
  struct Foo {
    int a;
    int b;
  };

  void dump(const A::Foo& v) {
      std::cout << v.a << v.b << std::endl;
  }
} // ns A

class B {
public:
   void dump() const {
       (void)std::for_each(std::begin(foo), std::end(foo),
                           [](const A::Foo &f){
                           dump(f); // <- fails here, I expected ADL to kick in
       });
   }
private:
   std::vector<A::Foo> foo = { A::Foo{}, A::Foo{} };
};

得到:

<source>: In lambda function:
21 : <source>:21:19: error: no matching function for call to 
'B::dump(const A::Foo&)'
         dump(f);
               ^
18 : <source>:18:10: note: candidate: void B::dump() const
         void dump() const {

为什么ADL在这里失败? 我假设编译器会找到B :: dump,但由于A :: Foo在同一名称空间中有转储(const Foo&amp;),编译器会将其添加为选项。但它不起作用。用-std = c ++ 17

编译

2 个答案:

答案 0 :(得分:1)

void dump() const {

问题是你已经在范围内有一个名为dump()的符号,在此方法中包含lambda调用。这是优先的。

如果您将此方法命名为dump2(),则查找会按预期成功完成。

The key rule here:

  

...除了参数的名称空间中查找   通常不合格名称考虑的范围和名称空间   查找

强调我的。 &#34;除了通常的非限定名称查找&#34;所考虑的范围和命名空间范围和命名空间之外。

&#34;通常&#34;非限定名称查找在调用类中查找dump()符号。完全停止。

答案 1 :(得分:1)

[basic.lookup.argdep]/3,强调我的:

  

X 成为非限定查找生成的查找集,让 Y 成为由参数相关查找生成的查找集(定义如下)。   如果 X 包含

     
      
  • 类成员声明
  •   
  • 块范围函数声明,它不是using声明或
  •   
  • 既不是功能也不是功能模板的声明
  •   
     

然后 Y 为空。