Answer the question
In order to leave comments, you need to log in
Why is a friend function defined inside a class with an inline type first parameter not available outside the class definition?
Operator overloading is syntactic sugar. The operators themselves are basically just functions. All operators in expressions containing only built-in data types cannot be modified. I saw an example where the definition of overloading a global binary operator for some reason is done inside the class.
The f5() function's parameter list starts with a built-in type. Why does the compiler not see f5() if there is not at least one parameter with type A in the parameter list?
void f1(int var) { ; }
class A {
int data;
public:
friend void f1(int var);
friend void f2(A a) { ; }
friend void f3(A a, int var) { ; }
friend void f4(int var, A a) { ; }
friend void f5(int var) { ; } //???
friend void operator% (int var, A a) { ; }
};
int main(void) {
A a;
//! a.f1(1); // class A' has no member named 'f1' , OK
//! a.f2(a); // class A' has no member named 'f2' , OK
//! a.f3(a, 3); // class A' has no member named 'f3' , OK
//! a.f4(4, a); //'class A' has no member named 'f4' , OK
//! a.f5(5); //'class A' has no member named 'f5' , OK
f1(1); // OK, global function
f2(a); // OK, global function
f3(a, 3); // OK, global function
f4(4, a); // OK, global function
//! f5(5); // was not declared in this scope; ???
//! a.operator%(1 , a); // 'class A' has no member named 'operator%' , OK
1%a; // OK, global function
return 0;
}
Answer the question
In order to leave comments, you need to log in
According to the standard , a friend function can only be defined at the place of declaration for a non-local class, and only if the function name is not qualified.
The first limitation is of little interest to us, and the second is quite significant.
The initially declared friend function, according to the standard , becomes a member of the namespace of the type for which it is declared friend.
We get such a situation. We have a namespace, even a global one, in which the type is defined. During the definition of this type, the initial declaration of the function as a friend of this type is made. As a result of this, the function, as it were, is declared to belong to the namespace in which the type is defined, but not quite.
The function f5
is not just initially declared, it is also defined at the place of the friend declaration. Her name is unambiguously unqualified by its definition.
We can also learn from the standard that a primary declared friendly name cannot be found by means of the standard search for qualified or unqualified names.
It is this result that we can observe in the question. The name f5
is not found.
All because the so-called. the names of hidden friends can only be found by means of ADL .
In short, Argument-Dependent Lookup relies on the types of arguments when calling a function, their namespaces, and the namespaces in which those types are declared.
ADL does not search namespaces for fundamental types. Therefore, the code f5(5);
is literally doomed to a translation error.
An initially declared friend function will be exclusively ADL-accessible until it is declared or defined in the same namespace as the friend type is defined. In this case, the function will become available to search for qualified or unqualified names.
For f5
, only the method with repeated declaration is available, because it's already defined.
Yes, only in this case f5
it will finally lose all meaning to be friendly to A
and become just a heavily hidden and confusing global function.
The essence of friendliness is in the disclosure of access, whichf5
relatively A
not used, tk. none of its parameters have the type A
.
As a result.
For ADL to find a function f5
, its parameters must include a parameter with type A
.
In order for UNL or QNL to be able to find a function f5
, it must be additionally declared outside the type A
in its namespace.
You are trying to call f1, etc., as if they were members of class A. But think about it, what's the point of declaring friend class members? Why is friendliness needed at all? To have access to private members of the class, but the members of the class already have access there. This is a pointless operation.
But the way the standard is made is that instead of a compilation error, functions defined via friend become global.
In theory, you should only declare them in the class (signature without body), and the definition (function body) should already be outside somewhere, as you did with f1.
Why is f5 not found? Try to transfer there, let's say a. The compiler will suddenly find the function and swear that it cannot convert A to int. But if you pass an int there, the compiler will lose the function.
Here is the tricky magic described in the standard - all sorts of heaps of rules for searching for names.
The standard says that when defining friend functions:
A name first declared in a friend declaration within a class or class template X becomes a member of the innermost enclosing namespace of X, but is not visible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at the namespace scope is provided - see namespaces for details.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question