If I have a function defined as friend inside a class. What is the namespace of that function?
namespace A{namespace B{
struct S{
friend void f(S const&){};
};
}}
int main(){
A::B::S s{};
f(s); // ok
::f(s); // not ok, no f in global namespace
A::B::f(s); // no f in A::B
A::B::S::f(s); // not ok, no f in A::B::S
}
Does it even have a namespace? Does it make sense for it to have a namespace?
What if I want to disambiguate a call in the commonly used idiom?
using std::swap;
swap(a, b);
Am I forced to define it outside the class and declare it a friend?
A friend declaration refers to a function from the narrowest enclosing namespace. However, it does not introduce the name of that function into the namespace
9.3.1.2 Namespace member definitions
3 If a friend declaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup or qualified lookup.
http://eel.is/c++draft/namespace.memdef#3
So, in your case A::B::f
is a friend. However, name f
does not exist in A::B
yet. You will not be able to refer to it as A::B::f
until you provide an explicit declaration of f
in A::B
.
Name lookup is able to find f
in unqualified f(s)
call through a special mechanism called Argument Dependent Lookup (ADL). ADL is the only mechanism that can "see" your function.
The function is in A::B
but it can only be found via ADL or Koenig Lookup.
The only way for it to be named in main is by introducing it outside the class definition.
Yes this is strange.
namespace A{namespace B{
inline void f(S const&);
struct S{
friend void f(S const&){};
};
}}
Now A::B::f
names f
.
This technique is something I use to introduce operators and other customization points. It also permits creating per-template instance functions on template classes that are not themselves templates.
template<class T>
struct foo {
friend void not_a_template( T ){}
};
template<class T>
void is_a_template(T){}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With