Anonymous namespaces and friend functions

R

Ronald Raygun

I have the class declared like this in the header fiel:

//header
class MyClass
{
public:
MyClass();
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
~MyClass();

friend int MyFriendFunc(const MyClass&);

private:
int m_i ;
};


//source
namespace
{
void MyFriendFunc(const MyClass& mc){ return mc.m_i++ ;}
}

//MyClass impl ...



I get compiltion errors (MyFriendFunc cannot access private member of
MyClass ...

using the ns resolution operator does not seem to work either:

friend int ::MyFriendFunc(const MyClass&);
 
V

Victor Bazarov

Ronald said:
I have the class declared like this in the header fiel:

//header
class MyClass
{
public:
MyClass();
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
~MyClass();

friend int MyFriendFunc(const MyClass&);

private:
int m_i ;
};


//source
namespace
{
void MyFriendFunc(const MyClass& mc){ return mc.m_i++ ;}
}

//MyClass impl ...



I get compiltion errors (MyFriendFunc cannot access private member of
MyClass ...

using the ns resolution operator does not seem to work either:

friend int ::MyFriendFunc(const MyClass&);

Try declaring the 'MyFriendFunc' _before_ the class and defining
it after.

V
 
B

bjeremy

Try declaring the 'MyFriendFunc' _before_ the class and defining
it after.

V

Also, shouldn't the MyFriendFunc() in the unamed namespace return an
'int' not 'void'...
 
A

Abhishek Padmanabh

Also, shouldn't the MyFriendFunc() in the unamed namespace return an
'int' not 'void'...

Even after incorporating both the above comments and disallowing
changing int member in the friend func (works on a reference to
const), Comeau rejects to compile:

class MyClass;
namespace{
int MyFriendFunc(const MyClass&);
}
//header
class MyClass
{
public:
MyClass();
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
~MyClass();
friend int MyFriendFunc(const MyClass&);
private:
int m_i ;
};
//source
namespace
{
int MyFriendFunc(const MyClass& mc){ return mc.m_i ;}
}

Comeau gives:

"ComeauTest.c", line 20: error: member "MyClass::m_i" (declared at
line 15) is
inaccessible
int MyFriendFunc(const MyClass& mc){ return mc.m_i ;}
^

"ComeauTest.c", line 20: warning: function "<unnamed>::MyFriendFunc"
was declared
but never referenced
int MyFriendFunc(const MyClass& mc){ return mc.m_i ;}
^
Why so?
 
A

Andrey Tarasevich

Abhishek said:
...
Even after incorporating both the above comments and disallowing
changing int member in the friend func (works on a reference to
const), Comeau rejects to compile:
...

It's quite possible that there's no way to do what you are trying to do.

When you define anonymous namespace like that

namespace {
int MyFriendFunc(const MyClass& mc);
}

it is pretty much equivalent to defining a namespace with some invented
name and then inserting a using-directive with that name

namespace unique_internal_name {
int MyFriendFunc(const MyClass& mc);
}

using unique_internal_name;

In this case the name 'MyFriendFunc' gets introduced into the global
namespace by that using-directive. It's been a matter of some debate
whether names introduced by using-directives/using-declarations should
be found by friend-declarations, see

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#138

Comeau compiler apparently doesn't think that the name should be found
in this case, which is why you get the error.
 
J

James Kanze

I have the class declared like this in the header fiel:
//header
class MyClass
{
public:
MyClass();
MyClass(const MyClass&);
MyClass& operator=(const MyClass&);
~MyClass();
friend int MyFriendFunc(const MyClass&);

In other words, a friend function in the same namespace as the
class.
private:
int m_i ;
};
//source
namespace
{
void MyFriendFunc(const MyClass& mc){ return mc.m_i++ ;}

Which is not in the same namespace as the class. (It also has a
different return type.)
//MyClass impl ...
I get compiltion errors (MyFriendFunc cannot access private
member of MyClass ...

Normal, you declare one function as friend, and implement
another.
using the ns resolution operator does not seem to work either:
friend int ::MyFriendFunc(const MyClass&);

Same problem.

I don't think you can declare a function in an anonymous
namespace as a friend (unless the class itself is in an
anonymous namespace). It makes sense, in a way, at least for
class definitions in a header file: the anonymous namespace is
distinct (i.e. has a different "name") for each translation
unit. So how could you specify it in a header file, without
violating the one definition rule. (If there were a syntax
which allowed it, then each time you included the header, you'd
define a different function as friend, thus violating the one
definition rule.)

What I usually do in such cases (or anytime I need to declare
implementation details in a header file) is defined a special
namespace. Something like:

namespace MyClassPrivate {
extern int myFriendFunction( MyClass const& ) ;
}

class MyClass
{
friend int MyClassPrivate::myFriendFunction( MyClass
const& ) ;
// ...
} ;

In such cases, I'll generally use a "using namespace
MyClassPrivate;" in the implementation files; in fact, if there
is more than one implementation file, I'll put the using
directive in the *local* header, if there is one. (This can be
viewed a bit as simulating access control for namespaces.)
 

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,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top