using a class in an unnamed namespace as friend

M

marco_segurini

Hi,

the following test program shows a solution to a problem I have had.

Now, this test program is compiled and linked by VS2003 and g++
while Comeau-on-line-compiler fails with this messages:

"ComeauTest.c", line 21: error: constant "COuter::ID" is inaccessible
int i = COuter::ID;
^
....some warning

1 error detected in the compilation of "ComeauTest.c".

who is wrong?

many thanks.
Marco.

//sample begin
namespace
{
class CInner;
}

class COuter
{
friend class CInner;

enum { ID = 5 };
};

namespace
{

class CInner
{
public:
CInner()
{
int i = COuter::ID;
}
};

} //!namespace

int main()
{
return 0;
}
 
R

Rob Williscroft

marco_segurini wrote in
in comp.lang.c++:
Hi,

the following test program shows a solution to a problem I have had.

Now, this test program is compiled and linked by VS2003 and g++
while Comeau-on-line-compiler fails with this messages:

"ComeauTest.c", line 21: error: constant "COuter::ID" is inaccessible
int i = COuter::ID;
^
...some warning

It would be unusual for Comeau/EDG to be wrong.
1 error detected in the compilation of "ComeauTest.c".

who is wrong?

VC++ and g++
//sample begin
namespace
{
class CInner;
}

class COuter
{
friend class CInner;

enum { ID = 5 };
};

Every things fine so far.
namespace
{

Ouch - This isn't the *same* nameless namespace defined above,
its a brand new one.
class CInner
{

Double Ouch - Not the the same CInner, this one
*isn't* a friend to COuter.
public:
CInner()
{
int i = COuter::ID;
}
};

} //!namespace

int main()
{
return 0;
}

In short you can't pre-*declare* anonymous things.

Rob.
 
T

tom_usenet

Ouch - This isn't the *same* nameless namespace defined above,
its a brand new one.

Are you sure? My reading of 7.3.1.1/1 suggests there is only one
anonymous namespace name per translation unit. e.g. the OPs code
should be "translated" to:

//sample begin
namespace unique
{
}
using namespace unique;
namespace unique
{
class CInner;
}

class COuter
{
friend class CInner;

enum { ID = 5 };
};

namespace unique
{

class CInner
{
public:
CInner()
{
int i = COuter::ID;
}
};

} //!namespace

int main()
{
return 0;
}

Interestingly, Comeau fails to compile the above too, and I think this
is an EDG bug (that also causes the failure of the original code). The
friend declaration in COuter should find unique::CInner according to
the name lookup rules for elaborated-type-specifiers. However, Comeau
considers the friend declaration to refer to ::CInner. My analysis may
be flawed of course...
In short you can't pre-*declare* anonymous things.

But you can according to Comeau. e.g.

namespace
{
extern int i;
}

int main()
{
i = 10; //expect linker error if you can't
}

namespace
{
int i = 1;
}

Tom
 
R

Rob Williscroft

tom_usenet wrote in in
comp.lang.c++:
Are you sure?

I was, but not any more.
My reading of 7.3.1.1/1 suggests there is only one
anonymous namespace name per translation unit.

I miss-remembered the conclusion of a thread on comp.std.c++.
I should have checked the standard myself of course.

Thanks for the correction.

Rob.
 
R

Rob Williscroft

tom_usenet wrote in in
comp.lang.c++:
//sample begin
namespace unique
{
}
using namespace unique;
namespace unique
{
class CInner;
}

class COuter
{
friend class CInner;

enum { ID = 5 };
};

namespace unique
{

class CInner
{
public:
CInner()
{
int i = COuter::ID;
}
};

} //!namespace

int main()
{
return 0;
}

Interestingly, Comeau fails to compile the above too, and I think this
is an EDG bug (that also causes the failure of the original code). The
friend declaration in COuter should find unique::CInner according to
the name lookup rules for elaborated-type-specifiers. However, Comeau
considers the friend declaration to refer to ::CInner. My analysis may
be flawed of course...

Seems right. Though ::CInner should refer to unique::CInner in
any case, so the friend declaration is unconditionaly inserting
a declaration for class CInner into ::.

The thread ( http://tinyurl.com/26dqo ) that I miss-remembered
contains this workaround (http://tinyurl.com/2ams9 ):

//sample begin
#define unique
//namespace unique {} using namespace unique;
namespace unique
{
namespace foo
{
class CInner;
}
}

class COuter
{
friend class foo::CInner;

/* friend class ::CInner; doesn't work.
g++ 3.4 and VC++ 7.1 accept it.
*/
enum { ID = 5 };
};

namespace unique
{
namespace foo
{
class CInner
{
public:
CInner()
{
int i = COuter::ID;
}
};
}
} //!namespace

int main()
{
return 0;
}

Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top