By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,652 Members | 1,694 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,652 IT Pros & Developers. It's quick & easy.

About friend declaration

P: n/a
I find friend declaration just very tricky. I tried the following
examples on both MingW(gcc 3.4.2) and VC++ 2005. The results are
surprising.

Example1:
namespace ns1
{
class Test
{
friend void func()
{
printf("func in %s\n", __FILE__);
}
};
}

int main()
{
ns1::func();
}

---End Example1---
gcc: compiles and works
VC++: compile error: 'func': candidate function(s) not accessible

Example2:
-file1.cpp
namespace ns1
{
class Test
{
friend void func();
};
}

int main()
{
ns1::func2("abc");
}

-file2.cpp
namespace ns1
{
void func()
{
printf("func in %s\n", __FILE__);
}
}
---end Example2---
gcc: compiles and works
VC++: compiles and works

I'm rather confused. Does a friend function declaration make it as if
it's also declared in the enclosing namespace? At least in example2,
it seems to be so.

What about Example1? What is the right behavior?
Jun 27 '08 #1
Share this Question
Share on Google+
6 Replies


P: n/a
WaterWalk wrote:
I find friend declaration just very tricky. I tried the following
examples on both MingW(gcc 3.4.2) and VC++ 2005. The results are
surprising.

Example1:
namespace ns1
{
class Test
{
friend void func()
{
printf("func in %s\n", __FILE__);
}
};
}

int main()
{
ns1::func();
}

---End Example1---
gcc: compiles and works
It does not on GCC 4.1.2.

error: 'func' is not a member of 'ns1'
VC++: compile error: 'func': candidate function(s) not accessible

Example2:
-file1.cpp
namespace ns1
{
class Test
{
friend void func();
};
}

int main()
{
ns1::func2("abc");
}
How does "func2" enter the picture here? This cannot compile as it is,
so you obviously did not post the actual code.
--
Christian Hackl
Jun 27 '08 #2

P: n/a
On May 24, 3:44 pm, WaterWalk <toolmas...@163.comwrote:
I find friend declaration just very tricky. I tried the
following examples on both MingW(gcc 3.4.2) and VC++ 2005. The
results are surprising.
Example1:
namespace ns1
{
class Test
{
friend void func()
{
printf("func in %s\n", __FILE__);
}
Note that although the function you define is ns1::func, the
declaration for this function is only visible in Test. Since
the function has no parameters, ADL won't enter into effect
either.
};
}
int main()
{
ns1::func();
The name shouldn't be visible here.
}
---End Example1---
gcc: compiles and works
Not with the version I have.
VC++: compile error: 'func': candidate function(s) not accessible
"not visible" would be a better message. Or simply that it
cannot find the function.

Earlier (pre-standard) versions of C++ injected the name of a
friend into the surrounding scope, so some compilers may still
do this for reasons of backwards compatibility.
Example2:
-file1.cpp
namespace ns1
{
class Test
{
friend void func();
};

}
int main()
{
ns1::func2("abc");
I presume you mean ns1::func.
}
-file2.cpp
namespace ns1
{
void func()
{
printf("func in %s\n", __FILE__);
}
}
---end Example2---
gcc: compiles and works
VC++: compiles and works
This should have the same problem as the above. There is no
declaration of ns1::func visible when you compile main, so the
code shouldn't compile. (Again, the g++ I have here doesn't
compile it. The error message is:
names.cc:20: error: ‘func’ is not a member of ‘ns1’
Not perfect, either: `func' cannot be found in `ns1' would be
better.)
I'm rather confused. Does a friend function declaration make
it as if it's also declared in the enclosing namespace?
No, but it did in pre-standard C++. (More correctly, it
injected the name into file scope---there weren't namespaces ini
pre-standard C++, so there was no namespace scope.)

I forget the reason why the committee changed this. (I've been
told at least a half dozen times. Each time, I recognize that
it is valid, but end up forgetting exactly what it was.) There
was discussion concerning the possibility of breaking existing
code, but in practice, no one could figure out a possible use
for a friend function that didn't have an argument which
depended on the class it was a friend of, and with such an
argument, ADL finds the function, even if the declaration isn't
visible.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #3

P: n/a
On May 25, 1:26 am, James Kanze <james.ka...@gmail.comwrote:
On May 24, 3:44 pm, WaterWalk <toolmas...@163.comwrote:
I find friend declaration just very tricky. I tried the
following examples on both MingW(gcc 3.4.2) and VC++ 2005. The
results are surprising.
Example1:
namespace ns1
{
class Test
{
friend void func()
{
printf("func in %s\n", __FILE__);
}

Note that although the function you define is ns1::func, the
declaration for this function is only visible in Test. Since
the function has no parameters, ADL won't enter into effect
either.
};
}
int main()
{
ns1::func();

The name shouldn't be visible here.
}
---End Example1---
gcc: compiles and works

Not with the version I have.
VC++: compile error: 'func': candidate function(s) not accessible

"not visible" would be a better message. Or simply that it
cannot find the function.

Earlier (pre-standard) versions of C++ injected the name of a
friend into the surrounding scope, so some compilers may still
do this for reasons of backwards compatibility.
Example2:
-file1.cpp
namespace ns1
{
class Test
{
friend void func();
};
}
int main()
{
ns1::func2("abc");

I presume you mean ns1::func.
}
-file2.cpp
namespace ns1
{
void func()
{
printf("func in %s\n", __FILE__);
}
}
---end Example2---
gcc: compiles and works
VC++: compiles and works

This should have the same problem as the above. There is no
declaration of ns1::func visible when you compile main, so the
code shouldn't compile. (Again, the g++ I have here doesn't
compile it. The error message is:
names.cc:20: error: ‘func’ is not a member of ‘ns1’
Not perfect, either: `func' cannot be found in `ns1' would be
better.)
I'm rather confused. Does a friend function declaration make
it as if it's also declared in the enclosing namespace?

No, but it did in pre-standard C++. (More correctly, it
injected the name into file scope---there weren't namespaces ini
pre-standard C++, so there was no namespace scope.)

I forget the reason why the committee changed this. (I've been
told at least a half dozen times. Each time, I recognize that
it is valid, but end up forgetting exactly what it was.) There
was discussion concerning the possibility of breaking existing
code, but in practice, no one could figure out a possible use
for a friend function that didn't have an argument which
depended on the class it was a friend of, and with such an
argument, ADL finds the function, even if the declaration isn't
visible.
Thanks for this information. But at the same time, I find some curious
statements in the c++ standard and some books:
c++ standard 3.3/4
In particular, elaborated-type-specifiers
(3.3.1) and friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;
these restrictions apply to that region.

c++ standard 3.3.1/6
[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace,
but they do not introduce new names into that namespace (7.3.1.2).

To me, they look to say the opposite things. What's more:
C++ Primer, 4th edition, in Chapter 12.5
A friend declaration introduces the named class or nonmember function
into the surrounding scope.

In the same chapter, an example is given:
class X
{
friend class Y;
friend void f();
};

class Z
{
Y *ymem; //ok, declaration for class Y introduced by friend in X
void g() {return ::f();} //ok, declaration of f introduced by X
};

Another source of confusion is how a friend declaration affects name
lookup in the class granting friendship? For example:
class X
{
public:
void show();
Y *py; // is Y visible ?
friend claxx Y
friend void f();
};

void X::show()
{
f(); //is f visible?
}
In X's member function definitions, will f be visible? In X's member
declarations, will Y be visible?

I searched in the standard, but didn't find clues in it's chapters
about name lookup(in 3.4).
Jun 27 '08 #4

P: n/a
On May 25, 2:32 pm, "Alf P. Steinbach" <al...@start.nowrote:
* WaterWalk:
On May 25, 1:26 am, James Kanze <james.ka...@gmail.comwrote:
On May 24, 3:44 pm, WaterWalk <toolmas...@163.comwrote:
>I find friend declaration just very tricky. I tried the
following examples on both MingW(gcc 3.4.2) and VC++ 2005. The
results are surprising.
Example1:
namespace ns1
{
class Test
{
friend void func()
{
printf("func in %s\n", __FILE__);
}
Note that although the function you define is ns1::func, the
declaration for this function is only visible in Test. Since
the function has no parameters, ADL won't enter into effect
either.
> };
}
int main()
{
ns1::func();
The name shouldn't be visible here.
>}
---End Example1---
gcc: compiles and works
Not with the version I have.
>VC++: compile error: 'func': candidate function(s) not accessible
"not visible" would be a better message. Or simply that it
cannot find the function.
Earlier (pre-standard) versions of C++ injected the name of a
friend into the surrounding scope, so some compilers may still
do this for reasons of backwards compatibility.
>Example2:
-file1.cpp
namespace ns1
{
class Test
{
friend void func();
};
}
int main()
{
ns1::func2("abc");
I presume you mean ns1::func.
>}
-file2.cpp
namespace ns1
{
void func()
{
printf("func in %s\n", __FILE__);
}
}
---end Example2---
gcc: compiles and works
VC++: compiles and works
This should have the same problem as the above. There is no
declaration of ns1::func visible when you compile main, so the
code shouldn't compile. (Again, the g++ I have here doesn't
compile it. The error message is:
names.cc:20: error: ‘func’ is not a member of ‘ns1’
Not perfect, either: `func' cannot be found in `ns1' would be
better.)
>I'm rather confused. Does a friend function declaration make
it as if it's also declared in the enclosing namespace?
No, but it did in pre-standard C++. (More correctly, it
injected the name into file scope---there weren't namespaces ini
pre-standard C++, so there was no namespace scope.)
I forget the reason why the committee changed this. (I've been
told at least a half dozen times. Each time, I recognize that
it is valid, but end up forgetting exactly what it was.) There
was discussion concerning the possibility of breaking existing
code, but in practice, no one could figure out a possible use
for a friend function that didn't have an argument which
depended on the class it was a friend of, and with such an
argument, ADL finds the function, even if the declaration isn't
visible.
Thanks for this information. But at the same time, I find some curious
statements in the c++ standard and some books:
c++ standard 3.3/4
In particular, elaborated-type-specifiers
(3.3.1) and friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;
these restrictions apply to that region.
c++ standard 3.3.1/6
[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace,
but they do not introduce new names into that namespace (7.3.1.2).

Yeah, it's inconsistent.

As far as I can recall there isn't an active issue on it, either.

There should be.

Cheers, & hth.,
I hope so. But maybe I misunderstand some statements in the C++
standard. Not sure.
Jun 27 '08 #5

P: n/a
On May 25, 8:32 am, "Alf P. Steinbach" <al...@start.nowrote:
* WaterWalk:
[...]
Thanks for this information. But at the same time, I find some curious
statements in the c++ standard and some books:
c++ standard 3.3/4
In particular, elaborated-type-specifiers
(3.3.1) and friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;
these restrictions apply to that region.
c++ standard 3.3.1/6
[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace,
but they do not introduce new names into that namespace (7.3.1.2).
Yeah, it's inconsistent.
As far as I can recall there isn't an active issue on it, either.
There should be.
Well, both quotes are from non-normative notes; there's no
ambiguity in the normative requirements. But the first one
should definitely be either corrected or dropped. And the
second one seems a bit ambiguous as well to me: a friend
declaration can introduce a new name into a namespace; it just
doesn't make it visible. (But I think that there is a more
general problem of vocabulary here.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #6

P: n/a
On May 27, 10:18 am, James Kanze <james.ka...@gmail.comwrote:
On May 25, 8:32 am, "Alf P. Steinbach" <al...@start.nowrote:
* WaterWalk:
[...]
Thanks for this information. But at the same time, I find some curious
statements in the c++ standard and some books:
c++ standard 3.3/4
In particular, elaborated-type-specifiers
(3.3.1) and friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;
these restrictions apply to that region.
c++ standard 3.3.1/6
[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace,
but they do not introduce new names into that namespace (7.3.1.2).
Yeah, it's inconsistent.
As far as I can recall there isn't an active issue on it, either.
There should be.
Well, both quotes are from non-normative notes; there's no
ambiguity in the normative requirements. But the first one
should definitely be either corrected or dropped. And the
second one seems a bit ambiguous as well to me: a friend
declaration can introduce a new name into a namespace; it just
doesn't make it visible. (But I think that there is a more
general problem of vocabulary here.)
While preparing to write up a request for an editorial change
here, I reread the quoted passages in context, and realize that
in context, they are quite clear: the friend declaration
introduces the name into the enclosing namespace, but does not
make it visible there.

This also clears up the question of vocabulary: when the
standard says that a name is "in" a given namespace, that means
that the name (or the entity designated by the name) is a member
of that namespace. When it speaks of scope, it uses the word
visibility or visible. Thus, in the initial example:

namespace NS {
class Foo {
friend void f() ;
} ;
}

The friend declaration introduces the name f into the namespace
NS, but does not make it visible (in scope) in the namespace NS.
In other words, the declaration declares a fully qualified name
::NS::f(), but the declaration is (visible) in the scope of
::NS::Foo.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #7

This discussion thread is closed

Replies have been disabled for this discussion.