Re: Befriending a nested type, can't seem to find a way which satisfies both GCC & VC
On 27 Okt., 08:18, Sebastian Karlsson <Sebastian.Karls...@mmorpgs.org>
wrote:
Hi, I'll get right to the point with a small example:
struct WantsFriends;
template< typename Type >
struct Root
{
struct Child
{
void Poke( const WantsFriends& a_Target );
};
};
struct WantsFriends
{
private:
// If I use this version, then VC will compile
template< typename Type >
friend struct Root;
// If I use this version, then GCC will compile
template< typename Type >
friend struct Root< Type >::Child;
void TouchMe( ) const {}
};
template< typename Type >
void Root< Type >::Child::Poke( const WantsFriends& a_Target )
{
a_Target.TouchMe();
}
int main()
{
WantsFriends target;
Root< int >::Child someObj;
someObj.Poke( target );
}
The standard draft which I looked at talks about the reverse case,
Which draft are you referring to?
where a nested type declares some other type as a friend. But seems to
mention nothing about the case where one wants to befriend a nested
type from another scope.
This statement is incorrect. Even the currently valid C++ standard
ISO/IEC 14882:2003(E) does provide wording for your example in
14.5.3 [temp.friend]/3:
"A friend template may be declared within a class or class template.
[..]. In these cases, all specializations of the friend
class or friend function template are friends of the class or class
template granting friendship. [Example:
class A {
template<class T> friend class B; // OK
template<class T> friend void f(T){ /* ... */ } // OK
};
?end example]"
This allows the friend declaration that is accepted by VC.
(Note that members of befriended classes or class templates
have also access according to
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45)
Further on 14.5.3 [temp.friend]/6 says:
"A member of a class template may be declared to be a
friend of a non-template class. In this case, the
corresponding member of every specialization of the class
template is a friend of the class granting friendship.
[Example:
template<class T> struct A {
struct B { };
void f();
};
class C {
template<class T> friend struct A<T>::B;
template<class T> friend void A<T>::f();
};
?end example]"
This allows the friend declaration that is accepted by gcc.
The interesting thing here is that VC seems
to transfer friendship to all the nested childs, which seems to be
against the standard but probably actually more than often the wanted
behaviour.
According to the most recent draft this interpretation
is correct.
VC however didn't like the syntax I use to make GCC happy,
it complains that I'm trying to redeclare Root::Child.
Given a compiler that is 14882:2003-compatible the syntax
accepted by gcc is the most specific friend nomination.
I wont conceal that the standard could be clearer. E.g.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#638
points out that above mentioned [temp.friend]/6 causes
an interpretation problem, because there does not exist
any guarantee that every specialization of the nominated
template does indeed have such an inner member.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]