Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the fully qualified name of a friend function defined inside of a class?

What is the fully qualified name of a friend function defined inside of a class?

I recently saw an example analogous to the following. What is the fully qualified name of val() below?

#include <iostream>  namespace foo {     class A {         int x;     public:         A(int x = 0) : x(x) { }          friend int val(const A &a) { return a.x; }     }; }  int main() {     foo::A a(42);      // val() found using ADL:     std::cout << val(a) << std::endl;      // foo::val(a); // error: 'val' is not a member of 'foo'     // foo::A::val(a); // error: 'val' is not a member of 'foo::A'      return 0;    } 

Is argument-dependent lookup the only way val() can be found?

Admittedly, this does not stem from a practical problem. I am simply looking to gain a better understanding.

like image 240
Szabolcs Avatar asked Nov 06 '17 11:11

Szabolcs


People also ask

Can friend function be defined inside class?

Friend functions can be defined (given a function body) inside class declarations. These functions are inline functions. Like member inline functions, they behave as though they were defined immediately after all class members have been seen, but before the class scope is closed (at the end of the class declaration).

How do you declare a friend function in C++?

A friend function is declared inside the class with a friend keyword preceding as shown below. class className{ …… friend returnType functionName(arg list); }; As shown above, the friend function is declared inside the class whose private and protected data members are to be accessed.

How would you define a friend function outside class?

A friend function of a class is defined outside that class' scope but it has the right to access all private and protected members of the class. Even though the prototypes for friend functions appear in the class definition, friends are not member functions.

Where we should declare a function as a friend to a class?

Explanation: Friend function can be declared either in private or public part of the class.


2 Answers

Is argument-dependent lookup the only way val() can be found?

Yes, it is the only way. To quote the holy standard at [namespace.memdef]/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.

So while val is a member of foo, it's not visible to lookup from the friend declaration alone. An out of class definition (which is also a declaration) is required to make it visible. For an inline definition (and no out-of-class declaration) it means ADL is the only way to call the function.


As an added bonus, C++ did once have a concept of "friend name injection". That however has been removed, and the rules for ADL adjusted as a replacement. A more detailed overview can be found in WG21 paper N0777 (pdf).

like image 92
StoryTeller - Unslander Monica Avatar answered Oct 02 '22 13:10

StoryTeller - Unslander Monica


C++ Standard [7.3.1.2/3 (of ISO/IEC 14882:2011)]:

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. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship). If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2). If the name in a friend declaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.

like image 27
msc Avatar answered Oct 02 '22 14:10

msc