Topic: Using friend member definition for specialization


Author: gp1@paradise.net.nz (Graeme Prentice)
Date: Tue, 22 Jul 2003 18:47:03 +0000 (UTC)
Raw View
On 17 Jul 2003 22:56:46 -0400, "Mirek Fidler" <cxl@volny.cz> wrote:


[multiposted to comp.std.c++ and c++.moderated]


>Update:
>
>Comeau seems to accept this variant:
>
[ quotation prefix removed from Mirek's code ]

 template <class T>
 void Foo(const T& x) { *x; }

 template<typename T>
 struct Special {
  friend void Foo(const T& x) {}
 };

 struct Alfa : Special<Alfa>
 {
 };

 void g()
 {
       Foo(Alfa());
  //  Foo(int()); // this fails in generic Foo variant on '*x'...
 }

>Can I rely on that this is a 100% legal C++ ?


It's legal but the standard is unclear (especially 11.4 para 5) on how
name lookup is supposed to work in this situation IMO.  14.6.5 para 2
suggests that only argument dependent lookup works if the friend
function is not explicitly declared at namespace scope.  Since it's
inconvenient to declare the non template Foo at namespace scope in this
case, I guess you're hoping that arg. dependent lookup will always work.
Comeau seems to use only ADL for this and GCC/Borland manage to find the
function without ADL  - this is probably because the standard is
unclear.


 ::Foo( Alfa() );  // fails with Comeau, ok with GCC

 Special<float> abc;
 // ...
      Foo( float(3) );   // fails with Comeau, ok with GCC & Borland



Foo( Alfa() ) succeeds with Comeau in calling the friend function
because argument dependent lookup finds it  - Alfa() is an
associated class.  Argument dependent lookup is used only in unqualified
function call, so with Comeau, the qualified call fails and so does Foo
( float ) because Special<float> is not an associated class.


< 3.4.2 para 3 (arg dependent lookup) says >
Any namespace scope friend functions declared in associated classes are
visible within their respective namespaces even if they are not visible
during an ordinary lookup (11.4).
<>


11.4 para 5 says ...
<quote>
A friend function defined in a class is in the (lexical) scope of the
class in which it is defined. A friend function defined outside the
class is not (3.4.1).
<>

What on earth do those two sentences mean ??  - if the friend function
is defined in the class, then (obviously) it's in the lexical scope of
the class   -  so what?  How does this affect name lookup  - it doesn't
say.

Defect report 143 removed the words "and classes" from a sentence near
the end of 3.4.2 para 2   -   this might make your code illegal,
depending on how you interpret 3.4.2 para 3.  This is where I get lost.


11.4 para 5 also says ...
A function can be defined in a friend declaration of a class if and only
if the class is a nonlocal class (9.8), the function name is
unqualified, and the function has namespace scope. [Example:
 class M {
  friend void f() { } // definition of global f, a friend of M,
     // not the definition of a member function
 };


What does "and the function has namespace scope" mean?  - how could it
not have namespace scope?   Why does it say "global f"  -  what if the
class is inside a named namespace  - which namespace does f belong to
then?  Do other f functions found in that namespace get considered.
Since f() takes no arguments in this case, an unqualified call could
never find it if it wasn't explicitly declared at namespace scope as
well, in this case.

Graeme

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Graeme Prentice <gp1@paradise.net.nz>
Date: Wed, 23 Jul 2003 03:43:16 GMT
Raw View
On 17 Jul 2003 22:56:46 -0400, "Mirek Fidler" <cxl@volny.cz> wrote:

[multiposted to comp.std.c++ and c++.moderated]


>Update:
>
>Comeau seems to accept this variant:
>
[ quotation prefix removed from Mirek's code ]

 template <class T>
 void Foo(const T& x) { *x; }

 template<typename T>
 struct Special {
  friend void Foo(const T& x) {}
 };

 struct Alfa : Special<Alfa>
 {
 };

 void g()
 {
       Foo(Alfa());
  //  Foo(int()); // this fails in generic Foo variant on '*x'...
 }

>Can I rely on that this is a 100% legal C++ ?


It's legal but the standard is unclear (especially 11.4 para 5) on how
name lookup is supposed to work in this situation IMO.  14.6.5 para 2
suggests that only argument dependent lookup works if the friend
function is not explicitly declared at namespace scope.  Since it's
inconvenient to declare the non template Foo at namespace scope in this
case, I guess you're hoping that arg. dependent lookup will always work.
Comeau seems to use only ADL for this and GCC/Borland manage to find the
function without ADL  - this is probably because the standard is
unclear.


 ::Foo( Alfa() );  // fails with Comeau, ok with GCC

 Special<float> abc;
 // ...
      Foo( float(3) );   // fails with Comeau, ok with GCC & Borland



Foo( Alfa() ) succeeds with Comeau in calling the friend function
because argument dependent lookup finds it  - Alfa() is an
associated class.  Argument dependent lookup is used only in unqualified
function call, so with Comeau, the qualified call fails and so does Foo
( float ) because Special<float> is not an associated class.


< 3.4.2 para 3 (arg dependent lookup) says >
Any namespace scope friend functions declared in associated classes are
visible within their respective namespaces even if they are not visible
during an ordinary lookup (11.4).
<>


11.4 para 5 says ...
<quote>
A friend function defined in a class is in the (lexical) scope of the
class in which it is defined. A friend function defined outside the
class is not (3.4.1).
<>

What on earth do those two sentences mean ??  - if the friend function
is defined in the class, then (obviously) it's in the lexical scope of
the class   -  so what?  How does this affect name lookup  - it doesn't
say.

Defect report 143 removed the words "and classes" from a sentence near
the end of 3.4.2 para 2   -   this might make your code illegal,
depending on how you interpret 3.4.2 para 3.  This is where I get lost.


11.4 para 5 also says ...
A function can be defined in a friend declaration of a class if and only
if the class is a nonlocal class (9.8), the function name is
unqualified, and the function has namespace scope. [Example:
 class M {
  friend void f() { } // definition of global f, a friend of M,
     // not the definition of a member function
 };


What does "and the function has namespace scope" mean?  - how could it
not have namespace scope?   Why does it say "global f"  -  what if the
class is inside a named namespace  - which namespace does f belong to
then?  Do other f functions found in that namespace get considered.
Since f() takes no arguments in this case, an unqualified call could
never find it if it wasn't explicitly declared at namespace scope as
well, in this case.

Graeme

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]