Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Scope of a friend function defined inside a class definition + a doubt

Reply
Thread Tools

Scope of a friend function defined inside a class definition + a doubt

 
 
Peter
Guest
Posts: n/a
 
      12-17-2010
We all know what a friend function of a given class is: it's a
function which is not a member of the class, but has an access to its
non-public members. Usually we just declare a friend function inside a
class definition and define it elsewhere (in global scope or as a
member function of another class):

class foo
{
friend void friendly_function(); // declaration without
definition
};

void friendly_function() {some code} // definition in a global
scope

Defined this way, friendly_function() is visible anywhere from where
it's defined to the end of file (unless overridden in some local scope
by a variable with the same name).

However, it's perfectly legal to place the DEFINITION of a friend
function inside the definition of our class:

class foo
{
friend void friendly_function() {some code} // definition inside a
class definition
};

My questions are:

1. What is the scope of friendly_function() now?

2. What is the purpose of defining a friend function inside a
definition of a class which befriends it? It seems quite confusing and
illogical to me, my intuition tells me only a declaration should be
allowed there. After all, why would anyone define a function which is
NOT a member of a class inside that class? Since this is syntactically
correct, there must be a reason for it, so please give me an example
of situation where such a definition can be useful.


Here comes my doubt. I have two, almost identical, snippets of code:

#include <iostream>
using namespace std;

class foo
{
int x;
friend void friendly_function(){} //empty DEFINITION
};

int main()
{
friendly_function();
return 0;
}

which doesn't compile: g++ and Comeau give an error message about
"friendly_function" identifier not being visible in main(), Visual C++
seems to be more precise: " 'friendly_function': candidate function(s)
not
accessible could be the friend function at :
'friendly_function' [may be found via
argument-dependent lookup]".


Interestingly though, the following fragment is compiled by all three:

#include <iostream>
using namespace std;

class foo
{
int x;
friend void friendly_function(foo&){} // empty
DEFINITION, like before
};

int main()
{
foo obj;
friendly_function(obj);
return 0;
}

As you can see, the only difference is that previously
friendly_function() took no arguments and now an object of foo class
is passed to it by reference. Why does such a small change change the
scope of friendly_function()? Previously it was inaccessible inside
main() to all three compilers and now all three have access to it.
Why?


 
Reply With Quote
 
 
 
 
Balog Pal
Guest
Posts: n/a
 
      12-17-2010
"Peter" <(E-Mail Removed)>
> However, it's perfectly legal to place the DEFINITION of a friend
> function inside the definition of our class:
>
> class foo
> {
> friend void friendly_function() {some code} // definition inside a
> class definition
> };
>
> My questions are:
>
> 1. What is the scope of friendly_function() now?


It's at "namespace scope" (IOW just outside the class), but not visible
except through ADL. You can check its presense: declare an illegal overload
(same params, different return type) and it will be rejected.

> 2. What is the purpose of defining a friend function inside a
> definition of a class which befriends it? It seems quite confusing and
> illogical to me, my intuition tells me only a declaration should be
> allowed there.


The function you wrote does not make sense of course -- it has no params so
ADL never finds it.
This feature is used mostly for operators related to the class or something
around. like operator << for streaming, binary operator +, and so on.
Certainly you can have a set of overloaded free functions with a good name
in a framework -- say serialize, some accessor shim, etc.

>After all, why would anyone define a function which is
> NOT a member of a class inside that class?


google for why we want to define operator + as a nonbember rather than
member.

> Here comes my doubt. I have two, almost identical, snippets of code:


Which are certainly far from identical...

> #include <iostream>
> using namespace std;
>
> class foo
> {
> int x;
> friend void friendly_function(){} //empty DEFINITION
> };
>
> int main()
> {
> friendly_function();
> return 0;
> }
>
> which doesn't compile: g++ and Comeau give an error message about
> "friendly_function" identifier not being visible in main(),


Well told.

>Visual C++
> seems to be more precise: " 'friendly_function': candidate function(s)
> not
> accessible could be the friend function at :
> 'friendly_function' [may be found via
> argument-dependent lookup]".


An this one gives you all the possible hints. If you don't know what the
message means look it up for more details. I'm sure pasting it in google
provides a ton of explanation.

> Interestingly though, the following fragment is compiled by all three:
>
> #include <iostream>
> using namespace std;
>
> class foo
> {
> int x;
> friend void friendly_function(foo&){} // empty
> DEFINITION, like before
> };
>
> int main()
> {
> foo obj;
> friendly_function(obj);
> return 0;
> }
>
> As you can see, the only difference is that previously
> friendly_function() took no arguments and now an object of foo class
> is passed to it by reference. Why does such a small change change the
> scope of friendly_function()?


The first one is void, and the other has an argument of user defined type --
so argument dependent lookup applies, and will add the related namespaces of
all its arguments. finding the function where it is, in foo's namespace.
(it would be conveniently found even if foo lived in some buried
namespacewithout qualification.


 
Reply With Quote
 
 
 
 
Garrett Hartshaw
Guest
Posts: n/a
 
      12-17-2010
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 12/17/2010 02:17 PM, Peter wrote:
> We all know what a friend function of a given class is: it's a
> function which is not a member of the class, but has an access to its
> non-public members. Usually we just declare a friend function inside a
> class definition and define it elsewhere (in global scope or as a
> member function of another class):
>
> class foo
> {
> friend void friendly_function(); // declaration without
> definition
> };
>
> void friendly_function() {some code} // definition in a global
> scope
>
> Defined this way, friendly_function() is visible anywhere from where
> it's defined to the end of file (unless overridden in some local scope
> by a variable with the same name).
>
> However, it's perfectly legal to place the DEFINITION of a friend
> function inside the definition of our class:
>
> class foo
> {
> friend void friendly_function() {some code} // definition inside a
> class definition
> };
>
> My questions are:
>
> 1. What is the scope of friendly_function() now?
>
> 2. What is the purpose of defining a friend function inside a
> definition of a class which befriends it? It seems quite confusing and
> illogical to me, my intuition tells me only a declaration should be
> allowed there. After all, why would anyone define a function which is
> NOT a member of a class inside that class? Since this is syntactically
> correct, there must be a reason for it, so please give me an example
> of situation where such a definition can be useful.
>
>
> Here comes my doubt. I have two, almost identical, snippets of code:
>
> #include <iostream>
> using namespace std;
>
> class foo
> {
> int x;
> friend void friendly_function(){} //empty DEFINITION
> };
>
> int main()
> {
> friendly_function();
> return 0;
> }
>
> which doesn't compile: g++ and Comeau give an error message about
> "friendly_function" identifier not being visible in main(), Visual C++
> seems to be more precise: " 'friendly_function': candidate function(s)
> not
> accessible could be the friend function at :
> 'friendly_function' [may be found via
> argument-dependent lookup]".
>
>
> Interestingly though, the following fragment is compiled by all three:
>
> #include <iostream>
> using namespace std;
>
> class foo
> {
> int x;
> friend void friendly_function(foo&){} // empty
> DEFINITION, like before
> };
>
> int main()
> {
> foo obj;
> friendly_function(obj);
> return 0;
> }
>
> As you can see, the only difference is that previously
> friendly_function() took no arguments and now an object of foo class
> is passed to it by reference. Why does such a small change change the
> scope of friendly_function()? Previously it was inaccessible inside
> main() to all three compilers and now all three have access to it.
> Why?
>
>


When a friend function is defined in a class, it is only in the scope of
that class, not injected into the enclosing scope. In the second case,
argument-dependent lookup is used, and the function is found. In the
first case, there is no argument, so argument-dependent lookup can not
be used.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.16 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJNC+/uAAoJEO0SzzQOdchNCg0P/3SFdsDuMKTw0CRC+xKVQFty
8YVzrnch4RG4zsmX5vzzSbLY0/ARaDDVQYpiBQMg7/di9wgTLxhPcyDS2hFc9+E7
jB9bk41VA4VsOSxE0jOaYIbfm+p0JnamZGu5dBTYouvMiEZ3If 38E0HZr+qtB8WA
timjeliUPy5giTcNLrBUsX1LdfbtOaZ7b0ZUm3xvSoYt1l/pGG016xQTeKtqf8B0
8SiE8apDKn1Y9asEiIk5JYCbJNl4JvXY206+cTDfxzBeOCl1a0 vML5oWSUfgvE7Y
yp54Kfk41h0mNaH6PqYjJDDhKww0BEXGYVNC/d1+Ap2/iLwS48JMM67jE2t1dSGp
acC0O8t24/t9YHf2apcRlciF5nDaGDxLYVN6k41fAEI1k8KRDe++xA3cySHq BfuK
X2TDTied+dUKgJGnZMrRIEtBVNtN2hOgWYBW8P54HCWGaiVW93 YBagpVxnzGBORB
Dr7Xe/r2ojr/6wzogc6TdW7iX9L8ZYLXxbE/Bki0SSKC1X4P/MRDMj0qCkT2bnPh
6uYl2JvrIOQUlmUpD5o6NoRebnyOWYC/bAoQhGRALsYZVVRkYhDafEao3J8reqLu
Yo6aTwJTFcD3Du4Xh8wAeojqzoYyHkmhrV6sfUiC0PfEYOOpDh LoEmFnnDB36Y8Y
ebOIqK9oqthExeW7pV9X
=zFHL
-----END PGP SIGNATURE-----
 
Reply With Quote
 
Peter
Guest
Posts: n/a
 
      12-18-2010
> When a friend function is defined in a class, it is only in the scope of
> that class, not injected into the enclosing scope. In the second case,
> argument-dependent lookup is used, and the function is found. In the
> first case, there is no argument, so argument-dependent lookup can not
> be used.


But if I change void friendly_function() to void
friendly_function(int) my code still doesn't compile. Does the
mechanism of argument-independent lookup require at least one of
friendly_function's arguments to be of user-defined (class) type in
order to work? Is this the only restriction? Last question: is ADL a
standard feature of C++ or is it only a sort of extension offered by
some compilers? Thanks for help, I promise to read about it before I
write here again.

 
Reply With Quote
 
Garrett Hartshaw
Guest
Posts: n/a
 
      12-18-2010
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 12/17/2010 07:02 PM, Peter wrote:
>> When a friend function is defined in a class, it is only in the scope of
>> that class, not injected into the enclosing scope. In the second case,
>> argument-dependent lookup is used, and the function is found. In the
>> first case, there is no argument, so argument-dependent lookup can not
>> be used.

>
> But if I change void friendly_function() to void
> friendly_function(int) my code still doesn't compile. Does the
> mechanism of argument-independent lookup require at least one of
> friendly_function's arguments to be of user-defined (class) type in
> order to work? Is this the only restriction? Last question: is ADL a
> standard feature of C++ or is it only a sort of extension offered by
> some compilers? Thanks for help, I promise to read about it before I
> write here again.
>


ADL is standard, and in order to find a friend function declared in a
class through ADL, at least one of the arguments needs to be of (or a
reference or pointer to) that class.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.16 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJNDBAbAAoJEO0SzzQOdchN2MkP/0h6PgAuWwlArGHfnHbddIf1
pgzRksb9gv5qzFiI+KwgEc2b4Sxd+sWGgSMpcpQv7s92TPgpXq kLPbkJXXW+Mt6Y
z6ck4j9ICgbEwREMApKIuLipII2LiHBLWsuUmvbTJSqOHn9oRE rsUFZUb5xrnp2d
MaBkZS0SxMYQWsi2EDNnBCWDWo8HP9iNv6ZvszF/TMCL9AfRwupYdMhdgSJUelvB
KH2Nh//aKI6JPxySwvYn6tnOFrA1Et1Z0G9zhKzWKQJ5sFzUiObSAsy3C DAdFHQb
BgkJaX07lfqvvrHlgPh96Tl8vDfIED7sBKu6uFUSy4UPYrr6yj JuMxqHoBLpJpOR
wns0JA1edne4rqUNMY5ZFdDHJGtKK2t9GE1vkbZqr0t26hcXgH UMpswQDHAqrYw/
6FRB2/+/EnaAF6EjRQchWxiAJF+cJQWvQDt9rJoYN9X3YjI2bj8aor8V+G MJHua7
t8n09wupc64t4VygC96DVgb/QiLeSOMVGP7eiA/Oz5hgYI29arla+DVePUL/mXHB
ZQoFlx7mCTCwVbo3WaSaBoMW7W7vz20PM+pr/ZEVpx7jREDsA04K5/jqVE8rXRBL
DV2kyCto6ORAWG2i5XayWfVsGSBTyqoxH7T51cjcwyNBppvM67 JpG3V77Rd7hpXA
maolTFxqqPtzrAV5T7b5
=oBwT
-----END PGP SIGNATURE-----
 
Reply With Quote
 
Peter
Guest
Posts: n/a
 
      12-18-2010
> mechanism of argument-independent lookup

Oops, I meant "dependent".
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      12-18-2010
On Dec 17, 7:17 pm, Peter <(E-Mail Removed)> wrote:
> We all know what a friend function of a given class is: it's a
> function which is not a member of the class, but has an access to its
> non-public members. Usually we just declare a friend function inside a
> class definition and define it elsewhere (in global scope or as a
> member function of another class):


I'd argue with your "usually". In my code, a friend function is
usually defined inline in the class. It's fairly rare for there
to be a definition (or an additional declaration) elsewhere.

In almost all other cases, there will be a declaration *before*
the class definition.

> class foo
> {
> friend void friendly_function(); // declaration without definition
> };


> void friendly_function() {some code} // definition in a global scope


> Defined this way, friendly_function() is visible anywhere from where
> it's defined to the end of file (unless overridden in some local scope
> by a variable with the same name).


> However, it's perfectly legal to place the DEFINITION of a friend
> function inside the definition of our class:


> class foo
> {
> friend void friendly_function() {some code} // definition inside a class definition
> };


> My questions are:


> 1. What is the scope of friendly_function() now?


The scope is the nearest enclosing namespace, just as in the
previous case. The visibility, however, is only within the
class; the compiler will only see the function in cases where it
looks inside the class, either because it is in class scope
(member function, etc.), or because ADL causes it to look inside
the class.

> 2. What is the purpose of defining a friend function inside a
> definition of a class which befriends it? It seems quite confusing and
> illogical to me, my intuition tells me only a declaration should be
> allowed there. After all, why would anyone define a function which is
> NOT a member of a class inside that class?


Why would anyone define any function inside a class?

In practice, it's usually used in templates (and the purpose of
friend is often just to allow defining a free function inside a
class---the function doesn't actually access any class members,
and in one frequent idiom, the class doesn't even have any
members). The problem is simple:

template<typename T>
class Toto
{
friend void f(Toto const& obj);
};

This declares a friend function f. The friend is a *function*,
not a template! So you have to define a (non-template) f for
every instantiation of the template. If, on the other hand, you
write:

template<typename T>
class Toto
{
friend void f(Toto const& obj)
{
// implementation...
}
};

The compiler will generate the implementation of f every time it
is used, for the class it is used with.

And, of course, ADL will cause the compiler to look inside the
class for such functions whenever the function is used. (Maybe.
ADL triggers on the types of the arguments, not the types that
might result from a conversion. So if Toto<T> has a converting
constructor Toto::Toto(T const&), and you call f with something
other than Toto<T>, the compiler will not look inside Toto<T>,
and will not find the function.)

This is most frequently used for operators, rather than named
functions. How do you declare and implement std:stream
operator<<(std:stream&, Toto<T> const&) otherwise. (Of
course, you could make it a template as well, and make the
template instantiation a friend. But using an inline
instantiation of a friend is easier and less verbose.)

There are many common idioms where non-member operators are
implemented using member operators, e.g. operator+ is a free
function implemented in terms of the member operator+=. In such
cases, it is usual to use some generic base class, along the
lines of:

template<typename T>
struct ArithmeticOperators
{
friend T operator+(T const& lhs, T const& rhs)
{
T result(lhs);
result += rhs;
return result;
}
// and so on, for all of the arithmetic operators.
};

The numeric class then inherits from this class, e.g.:

class NumericType : public ArithmeticOperators<NumericType>
{
public:
NumericType& operator+=(NumericType const& other);
// ...
};

and automatically gets the non-assignment binary operator for every
assignment operator it defines. (Note that the reason for
friend here is *only* to be able to define the class in the
function body. ArithmeticOperators has no members for the
friend's to access.)

I use this in a number of cases: ArithmeticOperators (for all of
the binary arithmetic and logical operators), Comparison
operators (==, <, etc. which forward to isEqual or compare, with
simple meta programming to use isEqual for == and !=, if it
exists, and otherwise compare), and IOOperators (<< and >>,
which forward to print and scan---less useful than the others,
unless print and scan are virtual).

--
James Kanze
 
Reply With Quote
 
ptyxs
Guest
Posts: n/a
 
      12-19-2010
Peter wrote :

> Since this is syntactically correct, there must be a reason for it,


I wonder whether it is right to assert that the reason for a given
construct to be legal is always (in C++ or widely in any language)
that the construct is useful or usable. Perhaps the reason may be, in
some cases (not necessarily in the present case), some internal
constraint of the language.
What do you think ?
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      12-20-2010
On Dec 19, 10:36 am, ptyxs <(E-Mail Removed)> wrote:
> Peter wrote :


> > Since this is syntactically correct, there must be a reason for it,


> I wonder whether it is right to assert that the reason for a given
> construct to be legal is always (in C++ or widely in any language)
> that the construct is useful or usable. Perhaps the reason may be, in
> some cases (not necessarily in the present case), some internal
> constraint of the language.
> What do you think ?


There are many different reasons why the committee might make
some particular construct legal. Perhaps the most general is
that they simply didn't see any reason to forbid it; the overall
philosophy is when in doubt, to allow something, rather than
forbid it. And there are certainly things you can do which
generally aren't very useful (but maybe someone will invent
a use for them in the future).

This is definitely not the case here: the construct is part of
a standard idiom, and when changes elsewhere threatended to make
it illegal, the committee actually made the necessary
modifications so that it remained legal.

--
James Kanze
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Friend function defined in class template is not in scope Mike C++ 6 01-20-2011 05:17 AM
Friend function defined in class template is not in scope Mike C++ 1 01-16-2011 08:13 AM
member function definition inside and outside class..function already defined error.. ypjofficial@indiatimes.com C++ 1 01-09-2006 09:49 AM
can a class definition inside another class's definition Jianli Shen C++ 1 03-13-2005 06:02 PM
help?: incomplete definition with complete definition in scope Ark C Programming 1 08-07-2004 04:21 PM



Advertisments