Quick friend question

A

Adrian

From the standard:-

"11.4.3. A function first declared in a friend declaration has
external linkage (3.5). Otherwise, the function retains
its previous linkage (7.1.1)."

Does this mean that if have a friend function in a class declaration
in a header file I do not have to put the function prototype outside
the class as well.

I usually do:
-----
class foo
{
public:
friend int foo_func();
};
int foo_func();
---------
but is this the same:-
--------------
class foo
{
public:
friend int foo_func();
};
-------------


Thanks


Adrian
 
J

James Kanze

From the standard:-
"11.4.3. A function first declared in a friend declaration has
external linkage (3.5). Otherwise, the function retains
its previous linkage (7.1.1)."
Does this mean that if have a friend function in a class
declaration in a header file I do not have to put the function
prototype outside the class as well.
I usually do:
-----
class foo
{
public:
friend int foo_func();};
int foo_func();
---------
but is this the same:-
--------------
class foo
{
public:
friend int foo_func();};
-------------

It depends. Both declare exactly the same function, with
exactly the same linkage. But in the second case, the scope of
the declaration is the class, and it will only be found when the
compiler does a name lookup which includes the class (either
because it is from a class member function, or due to ADL).
 
A

Adrian

It depends. Both declare exactly the same function, with
exactly the same linkage. But in the second case, the scope of
the declaration is the class, and it will only be found when the
compiler does a name lookup which includes the class (either
because it is from a class member function, or due to ADL).

But 11.4.1 says a friend cannot be in the scope of a class for name
looks if I am reading this correctly

"11.4.1 A friend of a class is a function or class that is not a
member of the class but is permitted to use the private and protected
member names from the class. The name of a friend is not in the scope
of the class, and the friend is not called with the member access
operators (5.2.5) unless it is a member of another class. [Example:
the following example illustrates the differences between members and
friends:"


Adrian
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
On Feb 15, 5:50 pm, Adrian <[email protected]> wrote:

[ ... ]
It depends. Both declare exactly the same function, with
exactly the same linkage. But in the second case, the scope of
the declaration is the class, and it will only be found when the
compiler does a name lookup which includes the class (either
because it is from a class member function, or due to ADL).

That's how things initially look, but it's not really the case. A friend
is always at namespace scope, regardless of where the declaration is
physically placed. In fact, you can even define the function inside of
the class definition, without it having any effect on scope. For
example, at least as I read things, the following code is well formed:

#include <iostream>

class X {
friend void f() { std::cout << "found"; }
};

int main() {
f();
return 0;
}

Of course, "well formed" does NOT imply recommended!
 
J

James Kanze

(e-mail address removed)>, (e-mail address removed)
says...
[ ... ]
It depends. Both declare exactly the same function, with
exactly the same linkage. But in the second case, the scope of
the declaration is the class, and it will only be found when the
compiler does a name lookup which includes the class (either
because it is from a class member function, or due to ADL).
That's how things initially look, but it's not really the
case. A friend is always at namespace scope, regardless of
where the declaration is physically placed.

There are two separate issues at hand. The first is where the
function is declared to exist---in the case of a friend, the
nearest enclosing namespace scope. The second is the scope of
the name being declared. And foo_func() in the second
example above has class scope. The name will only be found when
lookup includes that class scope, although it the name declares
a function in namespace scope.

This is a change in standard C++ with regards to classical C++.
In classical C++, the name of the friend was injected into the
enclosing file scope (classical C++ didn't have namespaces, but
it comes out to about the same). I forget the exact reasons,
but this caused some problems. And the only use of this feature
that the committee could find was the Barton and Nackman trick
(more or less what you explain below), which was covered by ADL
(which wasn't present in classical C++ either).
In fact, you can even define the function inside of the class
definition, without it having any effect on scope. For
example, at least as I read things, the following code is well
formed:
#include <iostream>
class X {
friend void f() { std::cout << "found"; }
};
int main() {
f();
return 0;
}

I don't think so. Nor do recent versions of g++: 3.2.3 accepts
it, but 4.1.0 complains: 'f' was not declared in this scope.

The situation is somewhat strange; it is the only situation I
know of where a name is declared in a specific scope, but is
introduced into a different scope. This doesn't affect the
declarative region in which the name is visible, but it does
affect where the name itself resides---a declaration of void f()
outside the class refers to the same void f() that you defined
as a friend in the class.

Change f() to take an X somehow as an argument, however, and ADL
will find the function. I regularly use something like:

template< typename T >
class ArithmeticOperators
{
friend T const operator+( T const& lhs, T const& rhs )
{
T result( lhs ) ;
result += rhs ;
return result ;
}
// And so on, for all of the operators for which there
// exists an <op>=.
}

To get the full set of operators, all I do is:

class Whatever : public ArithmeticOperators< Whatever >
{
public:
Whatever& operator+=( Whatever const& other ) ;
// And so on...
} ;

Saves a lot of typing.

Note that in this case, the friendship isn't used to access any
private members (there aren't any); it's only used to allow
defining a non-member function in the class. Similarly,
inheritance isn't used for any isA relationship; but only
because ADL pulls in not only the class, but any base classes as
well.
 
J

James Kanze

But 11.4.1 says a friend cannot be in the scope of a class for name
looks if I am reading this correctly
"11.4.1 A friend of a class is a function or class that is not a
member of the class but is permitted to use the private and protected
member names from the class. The name of a friend is not in the scope
of the class, and the friend is not called with the member access
operators (5.2.5) unless it is a member of another class. [Example:
the following example illustrates the differences between members and
friends:"

The name isn't in the scope of the class, but the friend
declaration is. The "declarative region" in which the friend
declaration is visible is that of the class.

Note that this is really no different than if you write:

void
f()
{
extern void g() ;
// ::g() is visible here...
}

// but not here...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top