Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

friend function defined inside a template class

Tags:

c++

c++11

A friend function named test() is defined inside a template class A:

template <typename T> class A {
public:
    friend void cs() {/* code */}
}

Another class inherits from template class A:

class B : public A<B> {}

In main function, I failed to call cs(), the compiler can not see its declaration if I don't provide a function declaration in the global scope:

int main(){
    cs()
}

But things are different when cs takes its template class T as an argument:

template <typename T> class A{
public:
    friend void cs(const T& t) {}
}

Now cs() can be successfully called in the main function without any decalration:

int main(){
    B b;
    cs(b);
}

If a function takes a user-defined class as its argument, I know the compiler would search the scope of the user-defined class. So which scope exactly is cs() defined? How it is possible that cs() is successfully called in the second case?

like image 485
刘卫东 Avatar asked Jan 29 '19 08:01

刘卫东


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).

Can we declare a template function as the friend of the class?

A template friend declaration can name a member of a class template A, which can be either a member function or a member type (the type must use elaborated-type-specifier).

How do you call a function in a template?

Defining a Function Template A function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

Can we define friend function outside the 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.


2 Answers

If a function takes a user-defined class as its argument, I know the compiler would search the scope of the user-defined class.

Yes, it's called ADL. When you write cs(b), the compiler searches for a function named cs. It can't find any, which is what is happening in your first example.

But now since cs takes a b, the compiler can also search b's scope for a function named cs. That wasn't possible in the first example because there were no parameters! In B it finds void cs(const B&) and so uses that.

So which scope exactly is cs() defined?

In the global scope but cs is not visible to name lookup without ADL.

How it is possible that cs() is successfully called in the second case?

As explained, cs can be found through ADL on B.

like image 171
Rakete1111 Avatar answered Sep 26 '22 20:09

Rakete1111


Note that the name cs introduced by friend declaration is not visible to ordinary name lookup; that's why the 1st case fails unless you provide a declaration at namespace scope.

A name first declared in a friend declaration within 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

And the name cs is found successfully in the 2nd case because of ADL; you specify a parameter for cs.

Argument-dependent lookup, also known as ADL, or Koenig lookup, is the set of rules for looking up the unqualified function names in function-call expressions, including implicit function calls to overloaded operators. These function names are looked up in the namespaces of their arguments in addition to the scopes and namespaces considered by the usual unqualified name lookup.

And

So which scope exactly is cs() defined?

The name cs become members of the innermost enclosing namespace of A, i.e. the global namespace here, but it's not visible for ordinary name lookup.

like image 45
songyuanyao Avatar answered Sep 26 '22 20:09

songyuanyao