alfC
alfC

Reputation: 16272

What is the namespace of a friend-defined function?

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?

Upvotes: 4

Views: 109

Answers (3)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275600

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){}

Upvotes: 4

AnT stands with Russia
AnT stands with Russia

Reputation: 320571

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.

Upvotes: 6

PStarczewski
PStarczewski

Reputation: 503

Yes, you define function outside and make it a friend to a certain class. It's absolutely independent function, but you allow it to acces certain class.

Every name first declared in a namespace is a member of that namespace. If a friend declaration in a non-local class first declares a class or function, the friend class or function is a member of the innermost enclosing namespace.

Upvotes: 1

Related Questions