On Mon, 10 Oct 2022 at 21:07, Federico Kircheis via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
If this is the wrong mailing list, sorry, maybe you can redirect me to
the correct one.

Yes, this is the right place.
 
Consider following program.


----
namespace ns{
     struct foo{
         friend void bar(const foo&){}
     };
}

void bar2(ns::foo& f){
   bar(f);
}

auto lambda = [](ns::foo& f_){bar(f_);};

struct foo2{
     ns::foo mf;
     void bar(){
         bar(this->mf); // (1)
         auto& f2 = mf; [&f2]{bar(f2);}(); // (2)
         [](ns::foo& f_){bar(f_);}(mf); // (3)
         bar2(mf); // (4)
         lambda(mf); // 5
         ns::bar(mf); // (6)
         ::bar(mf); // (7)
     }
};
----

1) does not compile, tries to call this->bar, no great, but OK

2,3) Still tries to call this->bar, even if this has not been captured

4,5) Works

6,7) do not compile, as expected

(tested with GCC, clang and MSVC)


I understand why 1,4,5,6,7 behave as they do, but fail to see why 2 and
3 should not compile and call the hidden friend function.

Name lookup proceeds through parent scopes before considering ADL. https://eel.is/c++draft/basic.lookup#unqual-2.sentence-2
The parent scope of a lamba scope is the scope that contains it. http://eel.is/c++draft/basic.scope#scope-2.1
 
4 and 5 are suboptimal workarounds because they need a new function, if
the code is templated it needs to go in the header file, and thus leak
an implementation detail, if 2 or 3 would work it would be possible to
keep the workaround local.
Or is there another way to tell the compiler not trying to call
this->bar, without resorting to 6,7 as they do not work in this case?

Yes, you can bring another namespace scope function `bar` into scope, then ADL will be considered (because the lookup set does not contain member functions).

namespace spoiler { void bar(); }
// ...
         auto& f2 = mf; [&f2]{using spoiler::bar; bar(f2);}(); // (2)

It's not a fully local solution, but `::spoiler::bar()` does not need to be defined or to know anything about `::ns::foo`.

I tried finding the relevant part in the standard why 2 and 3 do not
work, but failed to do so, can anyone pinpoint me in the right direction?

Best

Federico
--
Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion