Topic: Friends & Templates & Lookup


Author: Gafoor <rrocky@bigfoot.com>
Date: Wed, 26 Sep 2001 18:38:40 GMT
Raw View
As per Section 14.6.5 of the standard.

This should not compile

template<class T>
class number
{
public:
number(int x) { }

friend void gcd(number& x, number& y)
{/* */}

};

void g()
{
number<double> a(3), b(4);

gcd(a,b); // Well-formed
gcd(3,4); // ill-formed; gcd is not visible
}


So is there a way to make this work,

I tried the modification below, but it still doesn't
work.



template<class T>
class number;

template<class T>
void gcd(number<T>& x, number<T>& y)
{
/* */
}
template<class T>
class number
{
public:
number(int x) { }

friend void gcd<T>(number<T>& x, number<T>& y) ;

};

void g()
{
number<double> a(3), b(4);
gcd(a,b); // well-formed
gcd(3,4); // ill-formed; gcd is not visible
}

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Wed, 26 Sep 2001 19:29:29 GMT
Raw View
In article <t%os7.6178$ev2.10891@www.newsranger.com>, Gafoor
<rrocky@bigfoot.com> writes
>I tried the modification below, but it still doesn't
>work.
>
>
>
>template<class T>
>class number;
>
>template<class T>
>void gcd(number<T>& x, number<T>& y)
>{
>/* */
>}
>template<class T>
>class number
>{
>public:
>number(int x) { }
>
>friend void gcd<T>(number<T>& x, number<T>& y) ;
>
>};
>
>void g()
>{
>number<double> a(3), b(4);
>gcd(a,b); // well-formed
>gcd(3,4); // ill-formed; gcd is not visible
>}

You have to understand the motivation. The intent was to prevent
declaration of friend injecting visible names in outer scopes and then
allowing implicit conversions to match them.  Doing so simply produced
too many accidents and rude surprises.

Leave aside friendship for the moment, do you think the following code
should work:

template <typename T>
void gcd(number<T> &, number<T> &);

int main(){
  gcd(3, 4);
}

I hope not because it involves binding a temporary to a non-const
reference (even if the compiler can make the type deduction)




Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Gafoor <rrocky@bigfoot.com>
Date: Wed, 26 Sep 2001 19:49:37 GMT
Raw View
In article <5hwLELA3iis7EwQU@ntlworld.com>, Francis Glassborow says...
>
>You have to understand the motivation. The intent was to prevent
>declaration of friend injecting visible names in outer scopes and then
>allowing implicit conversions to match them.  Doing so simply produced
>too many accidents and rude surprises.
>
>Leave aside friendship for the moment, do you think the following code
>should work:
>
>template <typename T>
>void gcd(number<T> &, number<T> &);
>
>int main(){
>  gcd(3, 4);
>}
>
>I hope not because it involves binding a temporary to a non-const
>reference (even if the compiler can make the type deduction)

What if it's a const reference.

i.e.

template<class T>
class C;

template<class T>
void f(const C<T>& x)
{

}

template<class T>
class C
{
public:
C(int x) { }

};

int main()
{
f(3);
}

Is this supposed to work ?


---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: Francis Glassborow <francis.glassborow@ntlworld.com>
Date: Thu, 27 Sep 2001 18:43:07 GMT
Raw View
In article <%gqs7.6291$ev2.11204@www.newsranger.com>, Gafoor
<rrocky@bigfoot.com> writes
>What if it's a const reference.
>
>i.e.
>
>template<class T>
>class C;
>
>template<class T>
>void f(const C<T>& x)
>{
>
>}
>
>template<class T>
>class C
>{
>public:
>C(int x) { }
>
>};
>
>int main()
>{
>f(3);
>}
>
>Is this supposed to work ?

AFAIK the answer is still know. The compiler when it sees f(3) has no
reason to go hunting through class template definitions to see if any
one of them provides a conversion operator for a function whose only
declaration is in that template definition.

Francis Glassborow
I offer my sympathy and prayers to all those who are suffering
as a result of the events of September 11 2001.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: Fri, 28 Sep 2001 22:25:13 GMT
Raw View
Gafoor <rrocky@bigfoot.com> wrote:

> template<class T>
> class C;
>=20
> template<class T>
> void f(const C<T>& x)
> {
>=20
> }
>=20
> template<class T>=20
> class C=20
> {
> public:
> C(int x) { }
>=20
> };
>=20
> int main()
> {
> f(3);
> }
>=20
> Is this supposed to work ?

What should it do ? IOW, what would it mean for this code to 'work' ?

Lets disregard for now the fact that template argument deduction does
not go that far. [*]

Then for any type T, calling the specialization f< T > with argument (3)
requires a conversion sequence consisting of the user-defined conversion
int -> 'C<T> const &' for the argument. Thus all these (infinitely many)
overloaded functions [+] are equally good matches, thus making the call
rather ambiguous.

[+] e.g.=20
   f<int>( C<int> const &),=20
   f<long double>( C<long double> const &) or
   f<C<C<C<C<C<bool> > > > >(C<C<C<C<C<bool> > > > > const &);


[*] It does not look for standard conversion sequences capable of
converting the argument type to any of the (potentially infinite) set of
possible parameter types. One good reason for that is, that compilers do
have trouble resolving infinite sets of candidate functions in finite
time and memory.

Ciao, J=F6rg


--=20
J=F6rg Barfurth                         joerg.barfurth@attglobal.net
<<<<<<<<<<<<< using std::disclaimer;  <<<<<<<<<<<<<<<<<<<<<<<<<<<<
Software Developer                    http://www.OpenOffice.org
StarOffice Configuration              http://www.sun.com/staroffice

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: Fri, 28 Sep 2001 23:01:01 GMT
Raw View
Gafoor <rrocky@bigfoot.com> wrote:

> As per Section 14.6.5 of the standard.
>=20
> This should not compile
>=20
> template<class T>=20
> class number=20
> {
> public:
> number(int x) { }
>=20
> friend void gcd(number& x, number& y)=20
> {/* */}
>=20
> };
>=20
> void g()
> {
> number<double> a(3), b(4);
>=20
> gcd(a,b); // Well-formed
> gcd(3,4); // ill-formed; gcd is not visible
> }

Yes. The declarations of the various overloaded 'gcd()' functions are
not visible. Note that these are *not* function template
specializations, but plain functions. Each of these functions does exist
only when the according class template 'number<>' is instantiated.

That declarations of these functions are not visible at namespace scope
is a Godd Thing (TM). Otherwise dclaring an Object (or otherwise
instantiating a class template) could cause changes to overload-sets and
thus cause a different function to be called.

You can still refer to these functions without argument dependent
lookup, if you declare them (one by one or within a template):

void f()
{
  // declare one of these functions
  void gcd(number<int>&,number<int>&);

  // an refer to it
  void (*num_op)(number<int>&,number<int>&) =3D &gcd;
 =20
  // ...
}

template <class T>
int h()
{
   void gcd(T&,T&);

   T x(2);=20
   gcd(x,x);
   return 0;
}

int a =3D h<number<double> >();

> So is there a way to make this work,
>=20
> I tried the modification below, but it still doesn't
> work.

> template<class T>
> void gcd(number<T>& x, number<T>& y)
> {
> /* */           =20
> }

> gcd(3,4); // ill-formed; gcd is not visible

This is something completely different. Here gcd<> is a template and its
declaration is visible. But the template arguments cannot be deduced
from this call, and if they could be deduced you would try to bind a
temporary to a non-const reference.

Ciao, Joerg

--=20
J=F6rg Barfurth                         joerg.barfurth@attglobal.net
<<<<<<<<<<<<< using std::disclaimer;  <<<<<<<<<<<<<<<<<<<<<<<<<<<<
Software Developer                    http://www.OpenOffice.org
StarOffice Configuration              http://www.sun.com/staroffice

---
[ 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.research.att.com/~austern/csc/faq.html                ]