friend declared function call

S

Sven Köhler

Hi,

so i have some strange class declaration, which looks like this:


namespace wurst {
class bla {
friend bool foobla(const bla& v, int x) {
return true;
}
};
}


With this, the following code works:

wurst::bla foo;
foobla(foo, 2);


How do i access foobla in a more specific way? What the "full qualified
name" of foobla?

The following alternatives DON'T work:

wurst::foobla(foo,2)
wurst::bla::foobla(foo, 2);

Can you give a working alternative?


Regards,
Sven
 
C

Christopher

Hi,

so i have some strange class declaration, which looks like this:

namespace wurst {
class bla {
friend bool foobla(const bla& v, int x) {
return true;
}
};

}


Someone got confused there.
A friend function shouldn't be implemented in the class it is a friend
of. Otherwise, it wouldn't be a friend, but a method belonging to the
class instead.

I would expect something like:

namespace wurst
{
class bla
{
friend bool foobla(const bla & v, int x);

int m_value;

public:
bla(int value)
:
m_value(value)
{}
};

bool foobla(const bla & v, int x)
{
// Access to private data of bla is allowed because of frienship
if( x = bla.m_value )
{
return true;
}
}
}

and for it to be called like so:

wurst::bla foo(2);
bool result = wurst::foobla(foo, 2);

Where being a friend function gives the function "foobla" access to
"bla"'s private data.
 
I

Ian Collins

Christopher said:
Someone got confused there.
A friend function shouldn't be implemented in the class it is a friend
of. Otherwise, it wouldn't be a friend, but a method belonging to the
class instead.
That simply isn't true. A friend has to be declared and may also be
defined within the class definition.

Two classic examples are I/O operators and callback functions which
require extern C linkage.
 
I

Ian Collins

Sven said:
Hi,

so i have some strange class declaration, which looks like this:


namespace wurst {
class bla {
friend bool foobla(const bla& v, int x) {
return true;
}
};
}
Nothing particularly strange about that.
With this, the following code works:

wurst::bla foo;
foobla(foo, 2);
OK.

How do i access foobla in a more specific way? What the "full qualified
name" of foobla?

The following alternatives DON'T work:

wurst::foobla(foo,2)

This is OK.
wurst::bla::foobla(foo, 2);
This isn't. foobla() isn't a member of bla (this form would be used if
foobla() were a static member function).
 
I

Ian Collins

Christopher said:
Show example code please. I've searched my I/O libraries and cannot find the
keyword friend anywhere, so you must be talking of custom operators, and
then I still cannot fathom why the function wouldn't be a plain old class
method.
The output and input operators << and >> are often declared as free
functions, which may be friends of the class.
 
S

Sven Köhler

The following alternatives DON'T work:
This is OK.

No, it isn't. (At least, if it isn't a gcc bug)

gcc says something like "no member foobla in wurst".
 
S

Sven Köhler

The following alternatives DON'T work:
No, it isn't. (At least, if it isn't a gcc bug)

gcc says something like "no member foobla in wurst".

OK, minimal non-compiling example:

namespace wurst {
class bla {
friend bool foobla(const bla& v, int x) {
return true;
}
};
}

int main()
{
wurst::bla foo;
wurst::foobla(foo, 2);
return 0;
}


LANG=C g++ test.cpp gives:
test.cpp: In function 'int main()':
test.cpp:12: error: 'foobla' is not a member of 'wurst'
 
J

James Kanze

Sven Köhler wrote:
Nothing particularly strange about that.

Yes. ADL kicks in, and finds the function declared in scope
wurst::foo.

Strictly speaking, it's worst::foobla.
This is OK.

Not without some additional code. As written, the name foobla
is declared in the scope wurst::bla, and is only visible in this
scope. Despite the fact that the fully qualified name is
wurst::foobla, the name is not visible in the scope wurst. And
ADL doesn't apply to qualified names, so the compiler cannot
find the name.

For this to work, there must be a declaration:

namespace wurst {
extern bool foobla( bla const& v, int x ) ;
}

somewhere before this use.
This isn't. foobla() isn't a member of bla (this form would
be used if foobla() were a static member function).

The problem, of course, is that the scope and the qualification
don't agree, and that in the case of qualified name lookup, the
compiler requires both to match. When it looks the function up
in wurst::, it doesn't find it, because the declaration is not
in scope. And when it looks the name up in wurst::bla, it sees
the function, but doesn't consider it, because if the
qualification names a class, only class members (or members of
base classes) are considered.

It's not particularly intuitive, but that's the way it is. In
general, if a function is designed to work with a specific type
of object, don't qualify it, and count on ADL.
 
J

James Kanze

That simply isn't true. A friend has to be declared and may
also be defined within the class definition.

It's actually a fairly standard idiom for operators in general
(although it may be applied for normal functions as well). In a
lot of cases, in fact, the friend declaration is present not
because the function requires access to private members, but
because it allows definition in the class. The standard Barton
and Nackman trick, for example. (I use it regularly for
generating the binary operators from the <op>= forms, for
example. Or for generating a complete STL iterator interface
from a small set of iterator primitives.)
 
S

Sven Köhler

For this to work, there must be a declaration:
namespace wurst {
extern bool foobla( bla const& v, int x ) ;
}

somewhere before this use.

Works for me!

Thanks for explaining! Really saved my day.
 
M

Markus Moll

Hi
namespace wurst {
class bla {
friend bool foobla(const bla& v, int x) {
return true;
}
};
}

Defining a friend function inside a class is a bit weird. However, it's
allowed. The difference to defining it outside the class (as far as I can
see) is that it is in the scope of the class, it is not visible outside the
class and it is implicitly inline.

This means that you have to declare it in the surrounding namespace if you
want to use it there, and you don't have to qualify class members inside
the definition.
How do i access foobla in a more specific way? What the "full qualified
name" of foobla?

It is said:
The following alternatives DON'T work:

wurst::foobla(foo,2)

Would be correct if you had previously declared wurst::foobla:

namespace wurst // the wurst possible name ;-)
{
bool foobla(const bla& v, int x);
}
wurst::bla::foobla(foo, 2);

Definitely not.

Markus
 
C

Christopher

The output and input operators << and >> are often declared as free
functions, which may be friends of the class.

I've never seen those implemented _inside_ the class, but defined and
implemented outside the class and then made a friend of the class.
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top