On Dec 17, 7:17 pm, Peter <pil...@poczta.onet.pl> wrote:
> We all know what a friend function of a given class is: it's a
> function which is not a member of the class, but has an access to its
> non-public members. Usually we just declare a friend function inside a
> class definition and define it elsewhere (in global scope or as a
> member function of another class):
I'd argue with your "usually". In my code, a friend function is
usually defined inline in the class. It's fairly rare for there
to be a definition (or an additional declaration) elsewhere.
In almost all other cases, there will be a declaration *before*
the class definition.
> class foo
> {
> friend void friendly_function(); // declaration without definition
> };
> void friendly_function() {some code} // definition in a global scope
> Defined this way, friendly_function() is visible anywhere from where
> it's defined to the end of file (unless overridden in some local scope
> by a variable with the same name).
> However, it's perfectly legal to place the DEFINITION of a friend
> function inside the definition of our class:
> class foo
> {
> friend void friendly_function() {some code} // definition inside a class definition
> };
> My questions are:
> 1. What is the scope of friendly_function() now?
The scope is the nearest enclosing namespace, just as in the
previous case. The visibility, however, is only within the
class; the compiler will only see the function in cases where it
looks inside the class, either because it is in class scope
(member function, etc.), or because ADL causes it to look inside
the class.
> 2. What is the purpose of defining a friend function inside a
> definition of a class which befriends it? It seems quite confusing and
> illogical to me, my intuition tells me only a declaration should be
> allowed there. After all, why would anyone define a function which is
> NOT a member of a class inside that class?
Why would anyone define any function inside a class?
In practice, it's usually used in templates (and the purpose of
friend is often just to allow defining a free function inside a
class---the function doesn't actually access any class members,
and in one frequent idiom, the class doesn't even have any
members). The problem is simple:
template<typename T>
class Toto
{
friend void f(Toto const& obj);
};
This declares a friend function f. The friend is a *function*,
not a template! So you have to define a (non-template) f for
every instantiation of the template. If, on the other hand, you
write:
template<typename T>
class Toto
{
friend void f(Toto const& obj)
{
// implementation...
}
};
The compiler will generate the implementation of f every time it
is used, for the class it is used with.
And, of course, ADL will cause the compiler to look inside the
class for such functions whenever the function is used. (Maybe.
ADL triggers on the types of the arguments, not the types that
might result from a conversion. So if Toto<T> has a converting
constructor Toto::Toto(T const&), and you call f with something
other than Toto<T>, the compiler will not look inside Toto<T>,
and will not find the function.)
This is most frequently used for operators, rather than named
functions. How do you declare and implement std:

stream
operator<<(std:

stream&, Toto<T> const&) otherwise. (Of
course, you could make it a template as well, and make the
template instantiation a friend. But using an inline
instantiation of a friend is easier and less verbose.)
There are many common idioms where non-member operators are
implemented using member operators, e.g. operator+ is a free
function implemented in terms of the member operator+=. In such
cases, it is usual to use some generic base class, along the
lines of:
template<typename T>
struct ArithmeticOperators
{
friend T operator+(T const& lhs, T const& rhs)
{
T result(lhs);
result += rhs;
return result;
}
// and so on, for all of the arithmetic operators.
};
The numeric class then inherits from this class, e.g.:
class NumericType : public ArithmeticOperators<NumericType>
{
public:
NumericType& operator+=(NumericType const& other);
// ...
};
and automatically gets the non-assignment binary operator for every
assignment operator it defines. (Note that the reason for
friend here is *only* to be able to define the class in the
function body. ArithmeticOperators has no members for the
friend's to access.)
I use this in a number of cases: ArithmeticOperators (for all of
the binary arithmetic and logical operators), Comparison
operators (==, <, etc. which forward to isEqual or compare, with
simple meta programming to use isEqual for == and !=, if it
exists, and otherwise compare), and IOOperators (<< and >>,
which forward to print and scan---less useful than the others,
unless print and scan are virtual).
--
James Kanze