Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > About friend declaration

Reply
Thread Tools

About friend declaration

 
 
WaterWalk
Guest
Posts: n/a
 
      05-24-2008
I find friend declaration just very tricky. I tried the following
examples on both MingW(gcc 3.4.2) and VC++ 2005. The results are
surprising.

Example1:
namespace ns1
{
class Test
{
friend void func()
{
printf("func in %s\n", __FILE__);
}
};
}

int main()
{
ns1::func();
}

---End Example1---
gcc: compiles and works
VC++: compile error: 'func': candidate function(s) not accessible

Example2:
-file1.cpp
namespace ns1
{
class Test
{
friend void func();
};
}

int main()
{
ns1::func2("abc");
}

-file2.cpp
namespace ns1
{
void func()
{
printf("func in %s\n", __FILE__);
}
}
---end Example2---
gcc: compiles and works
VC++: compiles and works

I'm rather confused. Does a friend function declaration make it as if
it's also declared in the enclosing namespace? At least in example2,
it seems to be so.

What about Example1? What is the right behavior?
 
Reply With Quote
 
 
 
 
Christian Hackl
Guest
Posts: n/a
 
      05-24-2008
WaterWalk wrote:

> I find friend declaration just very tricky. I tried the following
> examples on both MingW(gcc 3.4.2) and VC++ 2005. The results are
> surprising.
>
> Example1:
> namespace ns1
> {
> class Test
> {
> friend void func()
> {
> printf("func in %s\n", __FILE__);
> }
> };
> }
>
> int main()
> {
> ns1::func();
> }
>
> ---End Example1---
> gcc: compiles and works


It does not on GCC 4.1.2.

error: 'func' is not a member of 'ns1'

> VC++: compile error: 'func': candidate function(s) not accessible
>
> Example2:
> -file1.cpp
> namespace ns1
> {
> class Test
> {
> friend void func();
> };
> }
>
> int main()
> {
> ns1::func2("abc");
> }


How does "func2" enter the picture here? This cannot compile as it is,
so you obviously did not post the actual code.


--
Christian Hackl
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      05-24-2008
On May 24, 3:44 pm, WaterWalk <(E-Mail Removed)> wrote:
> I find friend declaration just very tricky. I tried the
> following examples on both MingW(gcc 3.4.2) and VC++ 2005. The
> results are surprising.


> Example1:
> namespace ns1
> {
> class Test
> {
> friend void func()
> {
> printf("func in %s\n", __FILE__);
> }


Note that although the function you define is ns1::func, the
declaration for this function is only visible in Test. Since
the function has no parameters, ADL won't enter into effect
either.

> };
> }


> int main()
> {
> ns1::func();


The name shouldn't be visible here.

> }


> ---End Example1---
> gcc: compiles and works


Not with the version I have.

> VC++: compile error: 'func': candidate function(s) not accessible


"not visible" would be a better message. Or simply that it
cannot find the function.

Earlier (pre-standard) versions of C++ injected the name of a
friend into the surrounding scope, so some compilers may still
do this for reasons of backwards compatibility.

> Example2:
> -file1.cpp
> namespace ns1
> {
> class Test
> {
> friend void func();
> };
>
> }


> int main()
> {
> ns1::func2("abc");


I presume you mean ns1::func.

> }


> -file2.cpp
> namespace ns1
> {
> void func()
> {
> printf("func in %s\n", __FILE__);
> }
> }


> ---end Example2---
> gcc: compiles and works
> VC++: compiles and works


This should have the same problem as the above. There is no
declaration of ns1::func visible when you compile main, so the
code shouldn't compile. (Again, the g++ I have here doesn't
compile it. The error message is:
names.cc:20: error: ‘func’ is not a member of ‘ns1’
Not perfect, either: `func' cannot be found in `ns1' would be
better.)

> I'm rather confused. Does a friend function declaration make
> it as if it's also declared in the enclosing namespace?


No, but it did in pre-standard C++. (More correctly, it
injected the name into file scope---there weren't namespaces ini
pre-standard C++, so there was no namespace scope.)

I forget the reason why the committee changed this. (I've been
told at least a half dozen times. Each time, I recognize that
it is valid, but end up forgetting exactly what it was.) There
was discussion concerning the possibility of breaking existing
code, but in practice, no one could figure out a possible use
for a friend function that didn't have an argument which
depended on the class it was a friend of, and with such an
argument, ADL finds the function, even if the declaration isn't
visible.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
WaterWalk
Guest
Posts: n/a
 
      05-25-2008
On May 25, 1:26 am, James Kanze <(E-Mail Removed)> wrote:
> On May 24, 3:44 pm, WaterWalk <(E-Mail Removed)> wrote:
>
> > I find friend declaration just very tricky. I tried the
> > following examples on both MingW(gcc 3.4.2) and VC++ 2005. The
> > results are surprising.
> > Example1:
> > namespace ns1
> > {
> > class Test
> > {
> > friend void func()
> > {
> > printf("func in %s\n", __FILE__);
> > }

>
> Note that although the function you define is ns1::func, the
> declaration for this function is only visible in Test. Since
> the function has no parameters, ADL won't enter into effect
> either.
>
> > };
> > }
> > int main()
> > {
> > ns1::func();

>
> The name shouldn't be visible here.
>
> > }
> > ---End Example1---
> > gcc: compiles and works

>
> Not with the version I have.
>
> > VC++: compile error: 'func': candidate function(s) not accessible

>
> "not visible" would be a better message. Or simply that it
> cannot find the function.
>
> Earlier (pre-standard) versions of C++ injected the name of a
> friend into the surrounding scope, so some compilers may still
> do this for reasons of backwards compatibility.
>
> > Example2:
> > -file1.cpp
> > namespace ns1
> > {
> > class Test
> > {
> > friend void func();
> > };

>
> > }
> > int main()
> > {
> > ns1::func2("abc");

>
> I presume you mean ns1::func.
>
> > }
> > -file2.cpp
> > namespace ns1
> > {
> > void func()
> > {
> > printf("func in %s\n", __FILE__);
> > }
> > }
> > ---end Example2---
> > gcc: compiles and works
> > VC++: compiles and works

>
> This should have the same problem as the above. There is no
> declaration of ns1::func visible when you compile main, so the
> code shouldn't compile. (Again, the g++ I have here doesn't
> compile it. The error message is:
> names.cc:20: error: ‘func’ is not a member of ‘ns1’
> Not perfect, either: `func' cannot be found in `ns1' would be
> better.)
>
> > I'm rather confused. Does a friend function declaration make
> > it as if it's also declared in the enclosing namespace?

>
> No, but it did in pre-standard C++. (More correctly, it
> injected the name into file scope---there weren't namespaces ini
> pre-standard C++, so there was no namespace scope.)
>
> I forget the reason why the committee changed this. (I've been
> told at least a half dozen times. Each time, I recognize that
> it is valid, but end up forgetting exactly what it was.) There
> was discussion concerning the possibility of breaking existing
> code, but in practice, no one could figure out a possible use
> for a friend function that didn't have an argument which
> depended on the class it was a friend of, and with such an
> argument, ADL finds the function, even if the declaration isn't
> visible.
>


Thanks for this information. But at the same time, I find some curious
statements in the c++ standard and some books:
c++ standard 3.3/4
In particular, elaborated-type-specifiers
(3.3.1) and friend declarations (11.4) may introduce a (possibly not
visible) name into an enclosing namespace;
these restrictions apply to that region.

c++ standard 3.3.1/6
[Note: friend declarations refer to functions or classes that are
members of the nearest enclosing namespace,
but they do not introduce new names into that namespace (7.3.1.2).

To me, they look to say the opposite things. What's more:
C++ Primer, 4th edition, in Chapter 12.5
A friend declaration introduces the named class or nonmember function
into the surrounding scope.

In the same chapter, an example is given:
class X
{
friend class Y;
friend void f();
};

class Z
{
Y *ymem; //ok, declaration for class Y introduced by friend in X
void g() {return ::f();} //ok, declaration of f introduced by X
};

Another source of confusion is how a friend declaration affects name
lookup in the class granting friendship? For example:
class X
{
public:
void show();
Y *py; // is Y visible ?
friend claxx Y
friend void f();
};

void X::show()
{
f(); //is f visible?
}
In X's member function definitions, will f be visible? In X's member
declarations, will Y be visible?

I searched in the standard, but didn't find clues in it's chapters
about name lookup(in 3.4).
 
Reply With Quote
 
WaterWalk
Guest
Posts: n/a
 
      05-27-2008
On May 25, 2:32 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * WaterWalk:
>
>
>
> > On May 25, 1:26 am, James Kanze <(E-Mail Removed)> wrote:
> >> On May 24, 3:44 pm, WaterWalk <(E-Mail Removed)> wrote:

>
> >>> I find friend declaration just very tricky. I tried the
> >>> following examples on both MingW(gcc 3.4.2) and VC++ 2005. The
> >>> results are surprising.
> >>> Example1:
> >>> namespace ns1
> >>> {
> >>> class Test
> >>> {
> >>> friend void func()
> >>> {
> >>> printf("func in %s\n", __FILE__);
> >>> }
> >> Note that although the function you define is ns1::func, the
> >> declaration for this function is only visible in Test. Since
> >> the function has no parameters, ADL won't enter into effect
> >> either.

>
> >>> };
> >>> }
> >>> int main()
> >>> {
> >>> ns1::func();
> >> The name shouldn't be visible here.

>
> >>> }
> >>> ---End Example1---
> >>> gcc: compiles and works
> >> Not with the version I have.

>
> >>> VC++: compile error: 'func': candidate function(s) not accessible
> >> "not visible" would be a better message. Or simply that it
> >> cannot find the function.

>
> >> Earlier (pre-standard) versions of C++ injected the name of a
> >> friend into the surrounding scope, so some compilers may still
> >> do this for reasons of backwards compatibility.

>
> >>> Example2:
> >>> -file1.cpp
> >>> namespace ns1
> >>> {
> >>> class Test
> >>> {
> >>> friend void func();
> >>> };
> >>> }
> >>> int main()
> >>> {
> >>> ns1::func2("abc");
> >> I presume you mean ns1::func.

>
> >>> }
> >>> -file2.cpp
> >>> namespace ns1
> >>> {
> >>> void func()
> >>> {
> >>> printf("func in %s\n", __FILE__);
> >>> }
> >>> }
> >>> ---end Example2---
> >>> gcc: compiles and works
> >>> VC++: compiles and works
> >> This should have the same problem as the above. There is no
> >> declaration of ns1::func visible when you compile main, so the
> >> code shouldn't compile. (Again, the g++ I have here doesn't
> >> compile it. The error message is:
> >> names.cc:20: error: ‘func’ is not a member of ‘ns1’
> >> Not perfect, either: `func' cannot be found in `ns1' would be
> >> better.)

>
> >>> I'm rather confused. Does a friend function declaration make
> >>> it as if it's also declared in the enclosing namespace?
> >> No, but it did in pre-standard C++. (More correctly, it
> >> injected the name into file scope---there weren't namespaces ini
> >> pre-standard C++, so there was no namespace scope.)

>
> >> I forget the reason why the committee changed this. (I've been
> >> told at least a half dozen times. Each time, I recognize that
> >> it is valid, but end up forgetting exactly what it was.) There
> >> was discussion concerning the possibility of breaking existing
> >> code, but in practice, no one could figure out a possible use
> >> for a friend function that didn't have an argument which
> >> depended on the class it was a friend of, and with such an
> >> argument, ADL finds the function, even if the declaration isn't
> >> visible.

>
> > Thanks for this information. But at the same time, I find some curious
> > statements in the c++ standard and some books:
> > c++ standard 3.3/4
> > In particular, elaborated-type-specifiers
> > (3.3.1) and friend declarations (11.4) may introduce a (possibly not
> > visible) name into an enclosing namespace;
> > these restrictions apply to that region.

>
> > c++ standard 3.3.1/6
> > [Note: friend declarations refer to functions or classes that are
> > members of the nearest enclosing namespace,
> > but they do not introduce new names into that namespace (7.3.1.2).

>
> Yeah, it's inconsistent.
>
> As far as I can recall there isn't an active issue on it, either.
>
> There should be.
>
> Cheers, & hth.,
>


I hope so. But maybe I misunderstand some statements in the C++
standard. Not sure.
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-27-2008
On May 25, 8:32 am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * WaterWalk:


[...]
> > Thanks for this information. But at the same time, I find some curious
> > statements in the c++ standard and some books:
> > c++ standard 3.3/4
> > In particular, elaborated-type-specifiers
> > (3.3.1) and friend declarations (11.4) may introduce a (possibly not
> > visible) name into an enclosing namespace;
> > these restrictions apply to that region.


> > c++ standard 3.3.1/6
> > [Note: friend declarations refer to functions or classes that are
> > members of the nearest enclosing namespace,
> > but they do not introduce new names into that namespace (7.3.1.2).


> Yeah, it's inconsistent.


> As far as I can recall there isn't an active issue on it, either.


> There should be.


Well, both quotes are from non-normative notes; there's no
ambiguity in the normative requirements. But the first one
should definitely be either corrected or dropped. And the
second one seems a bit ambiguous as well to me: a friend
declaration can introduce a new name into a namespace; it just
doesn't make it visible. (But I think that there is a more
general problem of vocabulary here.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      05-27-2008
On May 27, 10:18 am, James Kanze <(E-Mail Removed)> wrote:
> On May 25, 8:32 am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
>
> > * WaterWalk:


> [...]


> > > Thanks for this information. But at the same time, I find some curious
> > > statements in the c++ standard and some books:
> > > c++ standard 3.3/4
> > > In particular, elaborated-type-specifiers
> > > (3.3.1) and friend declarations (11.4) may introduce a (possibly not
> > > visible) name into an enclosing namespace;
> > > these restrictions apply to that region.
> > > c++ standard 3.3.1/6
> > > [Note: friend declarations refer to functions or classes that are
> > > members of the nearest enclosing namespace,
> > > but they do not introduce new names into that namespace (7.3.1.2).

> > Yeah, it's inconsistent.
> > As far as I can recall there isn't an active issue on it, either.
> > There should be.


> Well, both quotes are from non-normative notes; there's no
> ambiguity in the normative requirements. But the first one
> should definitely be either corrected or dropped. And the
> second one seems a bit ambiguous as well to me: a friend
> declaration can introduce a new name into a namespace; it just
> doesn't make it visible. (But I think that there is a more
> general problem of vocabulary here.)


While preparing to write up a request for an editorial change
here, I reread the quoted passages in context, and realize that
in context, they are quite clear: the friend declaration
introduces the name into the enclosing namespace, but does not
make it visible there.

This also clears up the question of vocabulary: when the
standard says that a name is "in" a given namespace, that means
that the name (or the entity designated by the name) is a member
of that namespace. When it speaks of scope, it uses the word
visibility or visible. Thus, in the initial example:

namespace NS {
class Foo {
friend void f() ;
} ;
}

The friend declaration introduces the name f into the namespace
NS, but does not make it visible (in scope) in the namespace NS.
In other words, the declaration declares a fully qualified name
::NS::f(), but the declaration is (visible) in the scope of
::NS::Foo.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
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




Advertisments