Re: Friend functions and scoping
On Apr 13, 8:16 am, Paul Bibbings <paul.bibbi...@googlemail.com>
wrote:
In =A711.5.1 of TC++PL (Special Edition, 2000), "Finding Friends,"
Stroustrup says:
"Like a member declaration, a friend declaration does not
introduce a name into an enclosing scope."
A few lines earlier in the introduction to the section (11.5,
"Friends") he'd explicitly compared friend function
declarations to member function declarations, saying:
"Like a member function, a friend function is explicitly declared
in the declaration of the class of which it is a friend. It is
therefore as much a part of that interface as is a member function."
This is confusing me a little when I find, through working
examples, that the contrary of his first statement 'appears'
to be the case, despite his overall emphasis on the similarity
of the two cases.
Two possibilities behind your observations:
-- You're using an old compiler. In pre-standard C++, a friend
declaration injected the name into the surrounding scope, so
that it could be found. If this is the case, upgrade your
compiler.
-- You're confused by ADL. Although the friend name isn't
injected into the surrounding scope, friends will typically
have some argument which depends on the class, and will
cause the compiler to look into the class because of
argument dependent lookup.
Thus, to simplify his example to working code, consider:
#include <iostream>
namespace N {
class C {
char *_c;
public:
C(char *c): _c(c) { }
friend void f(C); // friend function
void g(); // member function
};
void (*p)(C) = &f; // [Stroustrup - error: no f()
in scope] compiles fine, with definition below
This should NOT compile. At this point in the code, there is no
name f which is visible.
}
// adding the definitions ...
void N::f(C c) { // friend scope: N::
std::cout << c._c << '\n';
}
void N::C::g() { // member scope: N::C::
std::cout << "In g()..." << '\n';
}
int main() {
N::C c("Hello, World!");
f(c); // uses the type of
parameter c to locate f() in N::
c.g();
}
As the definitions of member g() and friend f() show, whereas
g is scoped in this example to the class definition, that is
to N::C::, f is scoped to N::, which I would see as the
"enclosing scope" of C. So I'm a little confused by his "LIKE
a member declaration, a friend declaration does NOT introduce
a name into an enclosing scope." Rather, unlike the member
declaration, the friend declaration seems to being doing just
that, unless I am not understanding his words correctly.
It's difficult to explain clearly. The fully qualified name of
the function f, after the friend declaration, is ::N::f. The
function itself is in the surrounding namespace scope. But the
friend declaration does not introduce the name into this scope;
after the friend declaration, the name is still only visible in
the class scope ::N::C.
Furthermore, the definition of the function pointer is
supposed to fail, there being "no f() in scope." Of course,
without the definition of f below this it does indeed fail at
linking, but with the definition of f in place as above,
everything appears to be fine.
Not with my compiler. It looks like you're using an out of date
compiler, or you've encountered a bug in the compiler.
Very possibly I'm merely missing the intent of his meaning,
but I'm struggling to find a sense that better fits his words.
In particular, where the example he gives does not explicitly
include namespacing, thus putting f() in the global namespace,
it's hard to see exactly what "enclosing scope" it doesn't go
in to.
Note: The above has compiled for me with gcc 3.4.4 (cygwin)
and cl v. 15.00.30729.01 (VC++ Express), just in case this is
a non-standard compiler issue.
It doesn't compile with g++ 4.3.2.
Note that compilers may have delayed suppressing the injection
of friend names into the surrounding scope for fear of breaking
existing code. (At the least, I would expect a number of
versions where such code as the above triggered a warning,
rather than an error.) The fact remains that it is, according
to the standard, illegal.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34