Topic: can a class in an unnamed namespace be a friend?
Author: dsp@bdal.de (Daniel Spangenberg)
Date: Fri, 12 Sep 2003 23:02:13 +0000 (UTC) Raw View
Hello, Gianluca Silvestri !
Gianluca Silvestri schrieb:
> "David Abrahams" <dave@boost-consulting.com> ha scritto nel messaggio
> news:u65k2j7qw.fsf@boost-consulting.com...
> >
> > Anyone know a way to do this?
>
> Not possible with anonymous namespaces.
> I'll rewrite your code in a clearer way:
>
> namespace NS_this_is_a_unique_name_known_only_by_the_compiler
> {
> class M; //fwd decl
> }
> using NS_this_is_a_unique_name_known_only_by_the_compiler;
>
> class RD
> {
> friend class M; //here you're befriending class
> NS_this_is_a_unique_name_known_only_by_the_compiler::M;
> typedef int Q;
> };
>
> namespace NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler
> {
> class M
> {
> typedef RD::Q QQ;
> };
> }
> using NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler;
>
> So you see that it is impossible that the declaration of class M can ma=
tch
> the previous forwarding.
>
Your argumentation is wrong: The current standard guarantees that the
compiler-known
identifier for each unnamed namespace per translation unit is the same, s=
ee
7.3.1.1/p. 1:
"An unnamed namespace definition behaves as if it were replaced by
namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespacebody
}
where all occurrences of unique in a translation unit are replaced by the=
same
identifier and this identifier
differs from all other identifiers in the entire program."
So there is no "NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler=
" in
the
shown TU.
I think the reason is, that for class RD the friend declaration
class RD
{
friend class M;
typedef int Q;
}
denotes the nearest sourrounding namespace of RD (which seems to be the g=
lobal
one). Thus, it
cannot see M because you cannot denote it by its full-specified namespace
(which is unknown to us).
The explanation seems to be given by paragraph 3: Please have a look at t=
he
example
"Every name first declared in a namespace is a member of that namespace. =
If a
friend declaration in a
nonlocal class first declares a class or function83) the friend class or
function is a member of the innermost
enclosing namespace. The name of the friend is not found by simple name l=
ookup
until a matching declaration
is provided in that namespace scope (either before or after the class
declaration granting friendship). If
a friend function is called, its name may be found by the name lookup tha=
t
considers functions from namespaces
and classes associated with the types of the function arguments (3.4.2). =
When
looking for a prior
declaration of a class or a function declared as a friend, scopes outside=
the
innermost enclosing namespace
scope are not considered.[Example:
// Assume f and g have not yet been defined.
void h(int);
namespace A {
class X {
friend void f(X); // A::f is a friend
class Y {
friend void g(); // A::g is a friend
friend void h(int); // A::h is a friend
// ::h not considered
};
};
// A::f, A::g and A::h are not visible here
X x;
void g() { f(x); } // definition of A::g
void f(X) { /* ... */} // definition of A::f
void h(int) { /* ... */ } // definition of A::h
// A::f, A::g and A::h are visible here and known to be friends
}
using A::x;
void h()
{
A::f(x);
A::X::f(x); //error: f is not a member of A::X
A::X::Y::g(); // error: g is not a member of A::X::Y
}
=97end example]"
Sorry, I just had not the time to look **carefully** at it, but in the
hurry it seems the explantion for David's trouble.
Greetings,
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.jamesd.demon.co.uk/csc/faq.html ]
Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Fri, 12 Sep 2003 23:02:31 +0000 (UTC) Raw View
In article <Zy38b.47946$hE5.1687767@news1.tin.it>,
"Gianluca Silvestri" wrote:
> "David Abrahams" <dave@boost-consulting.com> ha scritto nel messaggio
> news:u65k2j7qw.fsf@boost-consulting.com...
>>
>> Anyone know a way to do this?
>
> Not possible with anonymous namespaces.
> I'll rewrite your code in a clearer way:
>
> namespace NS_this_is_a_unique_name_known_only_by_the_compiler
> {
> class M; //fwd decl
> }
> using NS_this_is_a_unique_name_known_only_by_the_compiler;
>
> class RD
> {
> friend class M; //here you're befriending class
> NS_this_is_a_unique_name_known_only_by_the_compiler::M;
> typedef int Q;
> };
>
> namespace NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler
> {
> class M
> {
> typedef RD::Q QQ;
> };
> }
> using NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler;
>
> So you see that it is impossible that the declaration of class M
> can match the previous forwarding.
I think you are wrong. The standard says (7.3.1.1/1):
"An unnamed-namespace-definition behaves as if it were
replaced by
namespace unique { /* empty body */ }
using namespace unique;
namespace unique { namespace-body }
where all occurrences of unique _in a translation unit_ are
replaced by the same identifier and this identifier differs
from all other identifiers in the entire program."
(my emphasis). So David's code should be fine *if* the anonymous
namespace definitions only appear in one translation unit.
However, I suspect he's looking for a way to put the class
definition in a header file.
My answer: use names along the lines of your header guards.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: dave@boost-consulting.com (David Abrahams)
Date: Thu, 11 Sep 2003 16:33:25 +0000 (UTC) Raw View
Anyone know a way to do this?
------- doesn't work -------
namespace
{
class M;
}
class RD
{
friend class M;
typedef int Q;
};
namespace {
class M { typedef RD::Q QQ; };
}
------- doesn't work -------
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: dishsi@tin.it ("Gianluca Silvestri")
Date: Fri, 12 Sep 2003 09:12:24 +0000 (UTC) Raw View
"David Abrahams" <dave@boost-consulting.com> ha scritto nel messaggio
news:u65k2j7qw.fsf@boost-consulting.com...
>
> Anyone know a way to do this?
Not possible with anonymous namespaces.
I'll rewrite your code in a clearer way:
namespace NS_this_is_a_unique_name_known_only_by_the_compiler
{
class M; //fwd decl
}
using NS_this_is_a_unique_name_known_only_by_the_compiler;
class RD
{
friend class M; //here you're befriending class
NS_this_is_a_unique_name_known_only_by_the_compiler::M;
typedef int Q;
};
namespace NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler
{
class M
{
typedef RD::Q QQ;
};
}
using NS_this_is_ANOTHER_unique_name_known_only_by_the_compiler;
So you see that it is impossible that the declaration of class M can match
the previous forwarding.
HTH
Gianluca
>
> ------- doesn't work -------
>
> namespace
> {
> class M;
> }
>
> class RD
> {
> friend class M;
> typedef int Q;
> };
>
> namespace {
> class M { typedef RD::Q QQ; };
> }
>
> ------- doesn't work -------
>
> --
> Dave Abrahams
> Boost Consulting
> www.boost-consulting.com
>
> ---
> [ 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.jamesd.demon.co.uk/csc/faq.html ]
>
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: Helge.Kruse-nospam@gmx.net ("Helge Kruse")
Date: Fri, 12 Sep 2003 09:12:54 +0000 (UTC) Raw View
Your sample does work with eVC++ 3.0.
A slight modification could be the typedef. But this is unrelated to your
question:
namespace
{
class M;
}
class RD
{
friend class M;
typedef int Q;
};
namespace
{
class M
{
// use scope to get RD from global namespace.
typedef ::RD::Q QQ;
public:
QQ GetNumber()
{
return 1;
}
};
}
But the class M in the unnamed namespace clashes with a class M in the
global namespace.
Helge
"David Abrahams" <dave@boost-consulting.com> schrieb im Newsbeitrag
news:u65k2j7qw.fsf@boost-consulting.com...
>
> Anyone know a way to do this?
>
> ------- doesn't work -------
>
> namespace
> {
> class M;
> }
>
> class RD
> {
> friend class M;
> typedef int Q;
> };
>
> namespace {
> class M { typedef RD::Q QQ; };
> }
>
> ------- doesn't work -------
>
> --
> Dave Abrahams
> Boost Consulting
> www.boost-consulting.com
>
> ---
> [ 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.jamesd.demon.co.uk/csc/faq.html ]
>
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Fri, 12 Sep 2003 09:13:51 +0000 (UTC) Raw View
dave@boost-consulting.com (David Abrahams) wrote
> Anyone know a way to do this?
>
> ------- doesn't work -------
>
> namespace
> {
> class M;
> }
>
> class RD
> {
> friend class M;
> typedef int Q;
> };
>
> namespace {
> class M { typedef RD::Q QQ; };
> }
>
> ------- doesn't work -------
Hmmmm.... Interesting.
One work around that should work is to nest another namespace within
the unnamed namespace and declare class M in it:
namespace {
namespace foo {
class M;
}
}
class RD
{
friend class foo::M;
typedef int Q;
};
namespace {
namespace foo {
class M { typedef RD::Q QQ; };
}
}
Comeau, gcc and Borland all accept this.
---
[ 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.jamesd.demon.co.uk/csc/faq.html ]