Topic: friend name lookup
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Sat, 8 Dec 2007 23:28:55 CST Raw View
On 28 Nov., 18:55, WaterWalk <toolmas...@163.com> wrote:
> I'm in bewilderment here. The compiler certainly works as you said:
> nested class can access even private members of its enclosing class
> through a pointer, a reference or an object of the enclosing class.
> But in C++ standard 11.8/1, it says:
>
> The members of a nested class have no special access to members of an
> enclosing class...
As I said, this is part of fix in #45 quoted in my posting -
The new draft contains the intended wording:
"A nested class is a member and as such has the same
access rights as any other member. The members of an
enclosing class have no special access to members of a
nested class; the usual access rules (clause 11) shall be
obeyed."
Note that I say intended, because the current one obviously
contradicts with itself. The following (ommitted) sentence
of your own quote above is:
"the usual access rules (clause 11) shall be obeyed."
If you take a look at these, there you find in [class.access]/1:
"- private; that is, its name can be used only by members
and friends of the class in which it is declared."
> One of my colleague told me that this code doesn't compile in VC6.
I belief that, just for this reason you can usually apply
the trick to declare the inner class first:
class Test;
friend class Test;
HTH & Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Mon, 10 Dec 2007 00:01:26 CST Raw View
[To the mods: This is my 2nd posting attempt, lets hope the best...]
On 28 Nov., 18:55, WaterWalk <toolmas...@163.com> wrote:
> I'm in bewilderment here. The compiler certainly works as you said:
> nested class can access even private members of its enclosing class
> through a pointer, a reference or an object of the enclosing class.
> But in C++ standard 11.8/1, it says:
>
> The members of a nested class have no special access to members of an
> enclosing class...
As I said, this is part of fix in #45 quoted in my posting -
The new draft contains the intended wording:
"A nested class is a member and as such has the same
access rights as any other member. The members of an
enclosing class have no special access to members of a
nested class; the usual access rules (clause 11) shall be
obeyed."
Note that I say intended, because the current one obviously
contradicts with itself. The following (ommitted) sentence
of your own quote above is:
"the usual access rules (clause 11) shall be obeyed."
If you take a look at these, there you find in [class.access]/1:
"- private; that is, its name can be used only by members
and friends of the class in which it is declared."
> One of my colleague told me that this code doesn't compile in VC6.
I belief that, just for this reason you can usually apply
the trick to declare the inner class first:
class Test;
friend class Test;
HTH & Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Sean Hunt <rideau3@gmail.com>
Date: Tue, 27 Nov 2007 16:24:44 CST Raw View
On Nov 27, 1:10 pm, WaterWalk <toolmas...@163.com> wrote:
> Hello. Consider the following code:
> <snipped code>
>
> When the friend declaration is put in (1), then this program compiles
> well, and both ::Test and Test2::Test have access to Test2's private
> members. But if the friend declaration is put in (2), this program
> won't compile. I tried it on both VC++ 2005 and gcc, and get the same
> results.
It should fail to compile the line " printf("In Test, %d\n",
t2.m); "
> Well, according to the ISO C++ standard, in 7.3.1.2/3, it says:
> If a friend declaration in non-local class first declares a class
> or function, the friend class or function is a member of the innermost
> enclosing namespace.
This only applies if no class or function that matches has already
been declared. In both cases, the first instance of Test that is found
is considered to be the target of the friend declaration.
Example:
class foo { friend void bar(); }
int main () { bar(); return 0; }
void bar() { }
In this case, the friend declaration in class foo declares bar,
allowing it to be used even before any other explicit declaration.
> When the friend declaration is put in (1), ::Test is visible, and that
> friend declaration shall refer to the global Test class, why the
> nested Test class in Test2 is also considered to be a friend of Test2?
It is, and that's the problem. Because Test2::Test is found
first, ::Test is not found for lookup on the friend declaration. As a
result, ::Test is not a friend of Test2, which is where your code
fails. Test2::Test doesn't need to be a friend - as a member of Test2,
it has access to all of Test2.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Tue, 27 Nov 2007 17:18:22 CST Raw View
On 27 Nov., 21:10, WaterWalk <toolmas...@163.com> wrote:
> class Test2;
> class Test
> {
> public:
> void show(Test2 const &t2);
> };
>
> class Test2
> {
> //friend class Test; // (1)
If you uncomment this, than [basic.lookup.elab] applies,
that is Test refers to the earlier declared class ::Test.
> private:
> int m;
> public:
> Test2() : m(3) {}
>
> class Test
> {
> public:
> void show(Test2 const &t2)
> {
> printf("In Test2::Test, %d\n", t2.m);
[N.B.: I expect a previous #include <stdio.h> here].
The earlier friend nomination (1) cannot refer to the
inner class, if the outer class ::Test is existing. If the
earlier ::Test declaration would not exist, (1) would
refer to the inner class. The intend of the standard
was that inner class have the same access rights as
other members of the class, so the Test2::Test
should have access to members of Test2 anyway.
In the current standard, this is not unambigiously
written, see
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
For this reason, you will find (older) compilers,
which would reject above access attempt. In this case
you often try this *inside* Test2:
class Test; // Forward declare inner Test
friend class Test; // Assign friend-ship to inner Test
Some other (older) compiler might still reject even this,
before
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#77
had clarified that problem.
> };
> //friend class Test; // (2)
If enabled, it would refer to Test2::Test, because the
declaration of Test2::Test has been seen, this is also
described in [basic.lookup.elab].
> When the friend declaration is put in (1), then this program compiles
> well, and both ::Test and Test2::Test have access to Test2's private
> members. But if the friend declaration is put in (2), this program
> won't compile. I tried it on both VC++ 2005 and gcc, and get the same
> results.
The compiler behaviour is correct under recent
interpretation.
> Well, according to the ISO C++ standard, in 7.3.1.2/3, it says:
> If a friend declaration in non-local class first declares a class
> or function, the friend class or function is a member of the innermost
> enclosing namespace.
This quote is insufficient to explain all details of
the rules, you also need to consider [basic.lookup.elab].
>
> When the friend declaration is put in (1), ::Test is visible, and that
> friend declaration shall refer to the global Test class, why the
> nested Test class in Test2 is also considered to be a friend of Test2?
As explained above.
HTH & Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Tue, 27 Nov 2007 17:39:06 CST Raw View
On 27 Nov., 23:24, Sean Hunt <ride...@gmail.com> wrote:
> This only applies if no class or function that matches has already
> been declared. In both cases, the first instance of Test that is found
> is considered to be the target of the friend declaration.
>
> Example:
>
> class foo { friend void bar(); }
>
> int main () { bar(); return 0; }
>
> void bar() { }
>
> In this case, the friend declaration in class foo declares bar,
> allowing it to be used even before any other explicit declaration.
This is *incorrect*. A friend declaration does not correspond
to a usual declaration and bar will not be found in main. See
[basic.scope.pdecl]/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).[..]]"
For a similar cases that were nominated as NAD's due to
this subtility, see e.g.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#165
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#95
Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Sean Hunt <rideau3@gmail.com>
Date: Tue, 27 Nov 2007 18:23:22 CST Raw View
On Nov 27, 4:39 pm, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
wrote:
> <snip>
Ah, thanks for clarifying that. Here I was thinking that they were
fully injected into that namespace. You've saved me a lot of future
debugging headaches!
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: WaterWalk <toolmaster@163.com>
Date: Wed, 28 Nov 2007 11:55:07 CST Raw View
On Nov 28, 7:18 am, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
wrote:
> On 27 Nov., 21:10, WaterWalk <toolmas...@163.com> wrote:
>
> > class Test2;
> > class Test
> > {
> > public:
> > void show(Test2 const &t2);
> > };
>
> > class Test2
> > {
> > //friend class Test; // (1)
>
> If you uncomment this, than [basic.lookup.elab] applies,
> that is Test refers to the earlier declared class ::Test.
>
> > private:
> > int m;
> > public:
> > Test2() : m(3) {}
>
> > class Test
> > {
> > public:
> > void show(Test2 const &t2)
> > {
> > printf("In Test2::Test, %d\n", t2.m);
>
> [N.B.: I expect a previous #include <stdio.h> here].
>
> The earlier friend nomination (1) cannot refer to the
> inner class, if the outer class ::Test is existing. If the
> earlier ::Test declaration would not exist, (1) would
> refer to the inner class. The intend of the standard
> was that inner class have the same access rights as
> other members of the class, so the Test2::Test
> should have access to members of Test2 anyway.
> In the current standard, this is not unambigiously
> written, see
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45
>
> For this reason, you will find (older) compilers,
> which would reject above access attempt. In this case
> you often try this *inside* Test2:
I'm in bewilderment here. The compiler certainly works as you said:
nested class can access even private members of its enclosing class
through a pointer, a reference or an object of the enclosing class.
But in C++ standard 11.8/1, it says:
The members of a nested class have no special access to members of an
enclosing class...
At the same time, however, the example given in that section can
compile(again both VC2005 and gcc)!
class E
{
private:
int x;
class I
{
private:
int n;
void f(E *p, int i)
{
p->x = i; //standard says it's an error, for E::x is private, but
in VC2005 and gcc, it compiles.
}
};
};
One of my colleague told me that this code doesn't compile in VC6.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: James Kanze <james.kanze@gmail.com>
Date: Wed, 28 Nov 2007 12:47:54 CST Raw View
On Nov 28, 12:39 am, "Daniel Kr gler" <daniel.krueg...@googlemail.com>
wrote:
> On 27 Nov., 23:24, Sean Hunt <ride...@gmail.com> wrote:
> > This only applies if no class or function that matches has
> > already been declared. In both cases, the first instance of
> > Test that is found is considered to be the target of the
> > friend declaration.
> > Example:
> > class foo { friend void bar(); }
> > int main () { bar(); return 0; }
> > void bar() { }
> > In this case, the friend declaration in class foo declares
> > bar, allowing it to be used even before any other explicit
> > declaration.
> This is *incorrect*. A friend declaration does not correspond
> to a usual declaration and bar will not be found in main. See
> [basic.scope.pdecl]/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).[..]]"
> For a similar cases that were nominated as NAD's due to
> this subtility, see e.g.
> http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#165http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#95
Yes. The scope of the declaration is the class, just like any
other declaration in a class. The entity being declared is,
however, declared in the enclosing namespace. It takes some
getting used to, but the scope of a declaration and where it is
declared are two different things. This is not the only case of
this in C++.
It's also worth pointing out that this is a change with regards
to the ARM, and some compilers may still implement friend name
injection. I don't know, however, since in all of the real
cases I'm familiar with, the friend has an argument of the class
type, which causes ADL to look at declarations in the class as
well (and so find the declaration). The final result is the
same (the code compiles and runs), even if the reasons why this
is so are different.
--
James Kanze (GABI Software) email:james.kanze@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
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Wed, 28 Nov 2007 14:33:27 CST Raw View
On 28 Nov., 19:47, James Kanze <james.ka...@gmail.com> wrote:
> It's also worth pointing out that this is a change with regards
> to the ARM, and some compilers may still implement friend name
> injection. I don't know, however, since in all of the real
> cases I'm familiar with, the friend has an argument of the class
> type, which causes ADL to look at declarations in the class as
> well (and so find the declaration). The final result is the
> same (the code compiles and runs), even if the reasons why this
> is so are different.
I agree. AFAIK the friend name injection was quite important
during times, when C++ (or the existing compilers - I don't know)
had less capabilities (If I correctly understand the explanations
given in "C++ Templates" during those dark ages function
template overloading were not feasible) and the Barton-Nackman
trick used the friend name injection to realize something
they called "restricted template expansion".
Later Bill Gibbons wrote
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1995/N0777.pdf
which pointed out the dangers of the to these times valid
rules (injection without argument dependency) and after
that the todays rules were developed. I hope I presented
this history not too wrong, because I myself did not
experience it in the way you did.
Greetings from Bremen,
Daniel
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "=?ISO-8859-1?Q?Daniel_Kr=FCgler?=" <daniel.kruegler@googlemail.com>
Date: Fri, 30 Nov 2007 13:54:14 CST Raw View
[To the mods: This is my 2nd posting attempt, lets hope the
best..]
On 28 Nov., 18:55, WaterWalk <toolmas...@163.com> wrote:
> I'm in bewilderment here. The compiler certainly works as you said:
> nested class can access even private members of its enclosing class
> through a pointer, a reference or an object of the enclosing class.
> But in C++ standard 11.8/1, it says:
>
> The members of a nested class have no special access to members of an
> enclosing class...
As I said, this is part of fix in #45 quoted in my posting -
The new draft contains the intended wording:
"A nested class is a member and as such has the same
access rights as any other member. The members of an
enclosing class have no special access to members of a
nested class; the usual access rules (clause 11) shall be
obeyed."
Note that I say intended, because the current one obviously
contradicts with itself. The following (ommitted) sentence
of your own quote above is:
"the usual access rules (clause 11) shall be obeyed."
If you take a look at these, there you find in [class.access]/1:
"- private; that is, its name can be used only by members
and friends of the class in which it is declared."
> One of my colleague told me that this code doesn't compile in VC6.
I belief that, just for this reason you can usually apply
the trick to declare the inner class first:
class Test;
friend class Test;
HTH & Greetings from Bremen,
Daniel Kr gler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: WaterWalk <toolmaster@163.com>
Date: Tue, 27 Nov 2007 14:10:57 CST Raw View
Hello. Consider the following code:
===code begin===
class Test2;
class Test
{
public:
void show(Test2 const &t2);
};
class Test2
{
//friend class Test; // (1)
private:
int m;
public:
Test2() : m(3) {}
class Test
{
public:
void show(Test2 const &t2)
{
printf("In Test2::Test, %d\n", t2.m);
}
};
//friend class Test; // (2)
};
void Test::show(Test2 const &t2)
{
printf("In Test, %d\n", t2.m);
}
int main()
{
Test2 t2;
Test t;
Test2::Test t2t;
t.show(t2);
t2t.show(t2);
}
===code end===
When the friend declaration is put in (1), then this program compiles
well, and both ::Test and Test2::Test have access to Test2's private
members. But if the friend declaration is put in (2), this program
won't compile. I tried it on both VC++ 2005 and gcc, and get the same
results.
Well, according to the ISO C++ standard, in 7.3.1.2/3, it says:
If a friend declaration in non-local class first declares a class
or function, the friend class or function is a member of the innermost
enclosing namespace.
When the friend declaration is put in (1), ::Test is visible, and that
friend declaration shall refer to the global Test class, why the
nested Test class in Test2 is also considered to be a friend of Test2?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]