template friend function of a template class

template friend function of a template class

Post by Carl Danie » Wed, 06 Jun 2001 03:06:20



In another thread ("Custom type qualifiers..."), Ross Smith posted
[abridged]:

Quote:> template <typename T, unsigned Mask> class qualified {
>   public:
>    // ...
>     template <unsigned Mask2> friend qualified<T, Mask2>
>       qualified_cast(qualified src) {
>         return qualified<T, Mask2>(src.value_);
>       }
> };

> // Define a couple of type qualifiers
> const unsigned magic(1);
> const unsigned tainted(2);

> int main() {
>   int i(42);                             // Plain int
>   qualified<int, magic> m;               // Magic int
>   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
>   mt = i;                                // OK
>   // m = mt;                             // This won't compile
>   m = qualified_cast<magic>(mt);         // But this will
>   return 0;
> }

> (Tested on GCC 2.95.3)

.... but apparently not tested with Comeau C++:

Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for ONLINE_EVALUATION
Copyright 1988-2001 Comeau Computing.  All rights reserved.
MODE:strict errors C++

"4893.c", line 42: error: identifier "qualified_cast" is undefined
    m = qualified_cast<magic>(mt);         // But this will
        ^

1 error detected in the compilation of "4893.c".

So who's right?  Is the OP's code valid C++?  If it is, what exactly is the
signature of the global function template qualified_cast<?????>(?????)?

-cd

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Martin Sebo » Thu, 07 Jun 2001 00:30:54



> In another thread ("Custom type qualifiers..."), Ross Smith posted
> [abridged]:

> > template <typename T, unsigned Mask> class qualified {
> >   public:
> >    // ...
> >     template <unsigned Mask2> friend qualified<T, Mask2>
> >       qualified_cast(qualified src) {
> >         return qualified<T, Mask2>(src.value_);
> >       }
> > };

> > // Define a couple of type qualifiers
> > const unsigned magic(1);
> > const unsigned tainted(2);

> > int main() {
> >   int i(42);                             // Plain int
> >   qualified<int, magic> m;               // Magic int
> >   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
> >   mt = i;                                // OK
> >   // m = mt;                             // This won't compile
> >   m = qualified_cast<magic>(mt);         // But this will
> >   return 0;
> > }

> > (Tested on GCC 2.95.3)

> .... but apparently not tested with Comeau C++:

> Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for ONLINE_EVALUATION
> Copyright 1988-2001 Comeau Computing.  All rights reserved.
> MODE:strict errors C++

> "4893.c", line 42: error: identifier "qualified_cast" is undefined
>     m = qualified_cast<magic>(mt);         // But this will
>         ^

> 1 error detected in the compilation of "4893.c".

> So who's right?  Is the OP's code valid C++?  If it is, what exactly is the
> signature of the global function template qualified_cast<?????>(?????)?

I think the (original) code is actually ill-formed and gcc is in error
for not diagnosing it. Tbe friend template qualified_cast() isn't found
during ordinary lookup unless it is explicitly declared at namespace
scope (14.6.5). Comeau lets this slide except in strict ansi (-A) mode.

Regards
Martin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Andrei Iltchen » Thu, 07 Jun 2001 00:41:12



> In another thread ("Custom type qualifiers..."), Ross Smith posted
> [abridged]:

> > template <typename T, unsigned Mask> class qualified {
> >   public:
> >    // ...
> >     template <unsigned Mask2> friend qualified<T, Mask2>
> >       qualified_cast(qualified src) {
> >         return qualified<T, Mask2>(src.value_);
> >       }
> > };

> > // Define a couple of type qualifiers
> > const unsigned magic(1);
> > const unsigned tainted(2);

> > int main() {
> >   int i(42);                             // Plain int
> >   qualified<int, magic> m;               // Magic int
> >   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
> >   mt = i;                                // OK
> >   // m = mt;                             // This won't compile
> >   m = qualified_cast<magic>(mt);         // But this will
> >   return 0;
> > }

> > (Tested on GCC 2.95.3)

> .... but apparently not tested with Comeau C++:

> Comeau C/C++ 4.2.45.2 (Apr 12 2001 10:06:52) for ONLINE_EVALUATION
> Copyright 1988-2001 Comeau Computing.  All rights reserved.
> MODE:strict errors C++

> "4893.c", line 42: error: identifier "qualified_cast" is undefined
>     m = qualified_cast<magic>(mt);         // But this will
>         ^

> 1 error detected in the compilation of "4893.c".

> So who's right?  Is the OP's code valid C++?  If it is, what exactly is the
> signature of the global function template qualified_cast<?????>(?????)?

Unfortunately the OP's code is not valid C++ and the EDG C++ front-end
issues a correct diagnostic.

The thing is that the following friend function declaration:

Quote:>     template <unsigned Mask2> friend qualified<T, Mask2>
>       qualified_cast(qualified src) {
>         return qualified<T, Mask2>(src.value_);
>       }

is just an indication to the compiler that the name 'qualified_cast'
is a member
of the nearest enclosing namespace, which happens to be the global
namespace. In no way does the declaration, which also happens to be a
definition, introduce the name 'qualified_cast' into the global
namespace scope.

Unless the function 'qualified_cast' is declared before the definition
of the class 'qualified' or after it, the name 'qualified_cast' can
only be found using argument-dependent lookup through the function
only argument's associated classes.

Given that in the function call expression

Quote:> m = qualified_cast<magic>(mt);

the argument 'mt' is a template-id, whose arguments all have
fundamental types, the set of classes associated with this argument is
empty, and the set of associated namespaces comprises only the global
namespace. As a result the name 'qualified_cast' cannot be found
through argument dependent lookup.

The only way to make the example well-formed is to add relevant
declaration of the function template 'qualified_cast' to the global
namespace. I guess you'll be a bit surprised at the form that the
declarations shall have:

template<unsigned Mask2>
qualified<unsigned,Mask2>  qualified_cast(qualified<unsigned,3>);

This one will suffice for the example shown. It follows that if you
decide to issue a statement 'm = qualified_cast<magic>(m)', another
global scope declaration of the form:
template<unsigned Mask2>
qualified<unsigned,Mask2>  qualified_cast(qualified<unsigned,1>);
will be necessary. And so on, and so forth, which in my opinion makes
the example a nuisance.

Regards,

Andrei Iltchenko.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Peter Dim » Fri, 08 Jun 2001 05:17:31




> > In another thread ("Custom type qualifiers..."), Ross Smith posted
> > [abridged]:

> > > template <typename T, unsigned Mask> class qualified {
> > >   public:
> > >    // ...
> > >     template <unsigned Mask2> friend qualified<T, Mask2>
> > >       qualified_cast(qualified src) {
> > >         return qualified<T, Mask2>(src.value_);
> > >       }
> > > };

> > > // Define a couple of type qualifiers
> > > const unsigned magic(1);
> > > const unsigned tainted(2);

> > > int main() {
> > >   int i(42);                             // Plain int
> > >   qualified<int, magic> m;               // Magic int
> > >   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
> > >   mt = i;                                // OK
> > >   // m = mt;                             // This won't compile
> > >   m = qualified_cast<magic>(mt);         // But this will
> > >   return 0;
> > > }

[...]

Quote:> Given that in the function call expression
> > m = qualified_cast<magic>(mt);
> the argument 'mt' is a template-id, whose arguments all have
> fundamental types, the set of classes associated with this argument is
> empty, and the set of associated namespaces comprises only the global
> namespace. As a result the name 'qualified_cast' cannot be found
> through argument dependent lookup.

I don't understand. Why is 'mt' a template-id? 'mt' is a variable of
type qualified<int, magic | tainted>, and this class should have an
associated namespace (in this case the global namespace,) so
qualified_cast<> should be reachable through Koenig lookup.

--
Peter Dimov
Multi Media Ltd.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Andrei Iltchenk » Fri, 08 Jun 2001 06:05:09





Quote:> > > In another thread ("Custom type qualifiers..."), Ross Smith posted
> > > [abridged]:

> > > > template <typename T, unsigned Mask> class qualified {
> > > >   public:
> > > >    // ...
> > > >     template <unsigned Mask2> friend qualified<T, Mask2>
> > > >       qualified_cast(qualified src) {
> > > >         return qualified<T, Mask2>(src.value_);
> > > >       }
> > > > };

> > > > // Define a couple of type qualifiers
> > > > const unsigned magic(1);
> > > > const unsigned tainted(2);

> > > > int main() {
> > > >   int i(42);                             // Plain int
> > > >   qualified<int, magic> m;               // Magic int
> > > >   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
> > > >   mt = i;                                // OK
> > > >   // m = mt;                             // This won't compile
> > > >   m = qualified_cast<magic>(mt);         // But this will
> > > >   return 0;
> > > > }

> [...]

> > Given that in the function call expression
> > > m = qualified_cast<magic>(mt);
> > the argument 'mt' is a template-id, whose arguments all have
> > fundamental types, the set of classes associated with this argument is
> > empty, and the set of associated namespaces comprises only the global
> > namespace. As a result the name 'qualified_cast' cannot be found
> > through argument dependent lookup.

> I don't understand. Why is 'mt' a template-id? 'mt' is a variable of
> type qualified<int, magic | tainted>, and this class should have an
> associated namespace (in this case the global namespace,) so
> qualified_cast<> should be reachable through Koenig lookup.

The argument dependent lookup is only concerned with the types of the
arguments supplied to a function call expression. Do you disagree that the
type of the object that the name 'mt' denotes is a template-id?

Cheers,

Andrei Iltchenko.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Peter Dim » Sat, 09 Jun 2001 02:42:12


[...]

Quote:> > > > > template <typename T, unsigned Mask> class qualified {
> > > > >   public:
> > > > >    // ...
> > > > >     template <unsigned Mask2> friend qualified<T, Mask2>
> > > > >       qualified_cast(qualified src) {
> > > > >         return qualified<T, Mask2>(src.value_);
> > > > >       }
> > > > > };

> > > > > // Define a couple of type qualifiers
> > > > > const unsigned magic(1);
> > > > > const unsigned tainted(2);

> > > > > int main() {
> > > > >   int i(42);                             // Plain int
> > > > >   qualified<int, magic> m;               // Magic int
> > > > >   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
> > > > >   mt = i;                                // OK
> > > > >   // m = mt;                             // This won't compile
> > > > >   m = qualified_cast<magic>(mt);         // But this will
> > > > >   return 0;
> > > > > }

> > [...]

> > > Given that in the function call expression
> > > > m = qualified_cast<magic>(mt);
> > > the argument 'mt' is a template-id, whose arguments all have
> > > fundamental types, the set of classes associated with this argument is
> > > empty, and the set of associated namespaces comprises only the global
> > > namespace. As a result the name 'qualified_cast' cannot be found
> > > through argument dependent lookup.

> > I don't understand. Why is 'mt' a template-id? 'mt' is a variable of
> > type qualified<int, magic | tainted>, and this class should have an
> > associated namespace (in this case the global namespace,) so
> > qualified_cast<> should be reachable through Koenig lookup.

> The argument dependent lookup is only concerned with the types of the
> arguments supplied to a function call expression. Do you disagree that the
> type of the object that the name 'mt' denotes is a template-id?

As I said, I'm not trying to disagree, but to understand. :-)

mt is of type 'qualified<int, magic | tainted>', right? Whether a type
can be called a template-id or not I don't know (I thought that the
template-id term refers to syntax, not semantics), but consider this
simple example:

#include <complex>

int main()
{
    std::complex<float> x;
    sin(x);

Quote:}

Here x is of type 'std::complex<float>', which is quite close in form.
Yet the argument-dependent lookup works fine in the function call
expression 'sin(x)'.

--
Peter Dimov
Multi Media Ltd.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Andrei Iltchenk » Sat, 09 Jun 2001 06:30:04






> [...]

> > > > > > template <typename T, unsigned Mask> class qualified {
> > > > > >   public:
> > > > > >    // ...
> > > > > >     template <unsigned Mask2> friend qualified<T, Mask2>
> > > > > >       qualified_cast(qualified src) {
> > > > > >         return qualified<T, Mask2>(src.value_);
> > > > > >       }
> > > > > > };

> > > > > > // Define a couple of type qualifiers
> > > > > > const unsigned magic(1);
> > > > > > const unsigned tainted(2);

> > > > > > int main() {
> > > > > >   int i(42);                             // Plain int
> > > > > >   qualified<int, magic> m;               // Magic int
> > > > > >   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
> > > > > >   mt = i;                                // OK
> > > > > >   // m = mt;                             // This won't compile
> > > > > >   m = qualified_cast<magic>(mt);         // But this will
> > > > > >   return 0;
> > > > > > }

> > > [...]

> > > > Given that in the function call expression
> > > > > m = qualified_cast<magic>(mt);
> > > > the argument 'mt' is a template-id, whose arguments all have
> > > > fundamental types, the set of classes associated with this argument
is
> > > > empty, and the set of associated namespaces comprises only the
global
> > > > namespace. As a result the name 'qualified_cast' cannot be found
> > > > through argument dependent lookup.

> > > I don't understand. Why is 'mt' a template-id? 'mt' is a variable of
> > > type qualified<int, magic | tainted>, and this class should have an
> > > associated namespace (in this case the global namespace,) so
> > > qualified_cast<> should be reachable through Koenig lookup.

> > The argument dependent lookup is only concerned with the types of the
> > arguments supplied to a function call expression. Do you disagree that
the
> > type of the object that the name 'mt' denotes is a template-id?

> As I said, I'm not trying to disagree, but to understand. :-)

> mt is of type 'qualified<int, magic | tainted>', right?

Right.

- Show quoted text -

Quote:> Whether a type
> can be called a template-id or not I don't know (I thought that the
> template-id term refers to syntax, not semantics), but consider this
> simple example:

> #include <complex>

> int main()
> {
>     std::complex<float> x;
>     sin(x);
> }

> Here x is of type 'std::complex<float>', which is quite close in form.
> Yet the argument-dependent lookup works fine in the function call
> expression 'sin(x)'.

There's a big difference between this example and that of Ross. 3.4.2/2 says
that for a template-id which is not a member template (since in both the
cases the template arguments are of the fundamental types or are non-type
parameters, there are no classes and namespace associated with them) the set
of associated classes is empty and the set of associated namespaces is the
namespace in which the template is defined.

As a result in the case of your example, x having type 'std::complex<float>'
has a set of associated namespaces S1: { std } and a set of associated
classes S2: {   }. Because the function template sin is defined in the
associated namespace std, it can be found by way of argument dependent
lookup.

In Ross's example mt has type '::qualified<int, magic|tainted>', hence its
set of associated namespaces S1 is { :: }, and its set of associated classes
S2: {   }. As the function template 'qualified_cast' is not declared in the
global namespace, it cannot be found.

Cheers,

Andrei Iltchenko.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

template friend function of a template class

Post by Peter Dim » Sun, 10 Jun 2001 05:05:47


[...]

[Original example]

Quote:> template <typename T, unsigned Mask> class qualified {
>   public:
>    // ...
>     template <unsigned Mask2> friend qualified<T, Mask2>
>       qualified_cast(qualified src) {
>         return qualified<T, Mask2>(src.value_);
>       }
> };

> // Define a couple of type qualifiers
> const unsigned magic(1);
> const unsigned tainted(2);

> int main() {
>   int i(42);                             // Plain int
>   qualified<int, magic> m;               // Magic int
>   qualified<int, (magic | tainted)> mt;  // Magic, tainted int
>   mt = i;                                // OK
>   // m = mt;                             // This won't compile
>   m = qualified_cast<magic>(mt);         // But this will
>   return 0;
> }

[...]

- Show quoted text -

Quote:> > #include <complex>

> > int main()
> > {
> >     std::complex<float> x;
> >     sin(x);
> > }

> There's a big difference between this example and that of Ross. 3.4.2/2 says
> that for a template-id which is not a member template (since in both the
> cases the template arguments are of the fundamental types or are non-type
> parameters, there are no classes and namespace associated with them) the set
> of associated classes is empty and the set of associated namespaces is the
> namespace in which the template is defined.

> As a result in the case of your example, x having type 'std::complex<float>'
> has a set of associated namespaces S1: { std } and a set of associated
> classes S2: {   }. Because the function template sin is defined in the
> associated namespace std, it can be found by way of argument dependent
> lookup.

> In Ross's example mt has type '::qualified<int, magic|tainted>', hence its
> set of associated namespaces S1 is { :: }, and its set of associated classes
> S2: {   }. As the function template 'qualified_cast' is not declared in the
> global namespace, it cannot be found.

Ok. Now consider this:

template<class T> class X
{
public:
    friend void f(X const &) {}

Quote:};

int main()
{
  X<void> x;
  f(x);

Quote:}

x has type ::X<void>, S1 = { :: }, S2 = { }, f() is not declared in
the global namespace, but the call f(x) works. Odd stuff. :-)

--
Peter Dimov
Multi Media Ltd.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]

 
 
 

1. use of a template function that is friend to a template class

 I have a template fucntion declared (that's what I believe) to be
friend of a template class. Upon usage of this function, it appears as
if the function is not considered to be friend, in fact the compiler
issues error messages regarding access violation of protected members of
the class.

The classes:

template <class T> class Tmatrix;

template <class T> class Tvector {
  friend Tmatrix <class T>;
 protected:
  int size;
  T *vec;
  int range(int);             //index check
 public:
.............
template <class T> friend T scalar(const Tvector<class T>&, const
Tvector<class T>&); // scalar product.
..........

template <class T>
T scalar(const Tvector <class T>  &u, const Tvector <class T> &v) //
scalar product operator
{ T t = 0;
 int n=u.size;
 if (u.size!=v.size) error("Scalar product can only be done on vectors
of equal sizes!");
 for (int i=0; i<n; ++i)
   t += u.vec[i] * v.vec[i];
 return t;

the compiler message:

-- vecmath_template.h: In function `int scalar<int>(const class
Tvector<int> &, const class Tvector<int> &)':
matrices.cpp:45:   instantiated from here
vecmath_template.h:216: member `size' is a protected member of class
`Tvector<int>'
vecmath_template.h:217: member `size' is a protected member of class
`Tvector<int>'
vecmath_template.h:217: member `size' is a protected member of class
`Tvector<int>'
vecmath_template.h:219: member `vec' is a protected member of class
`Tvector<int>'
vecmath_template.h:219: member `vec' is a protected member of class
`Tvector<int>'

please help to clarify this situation.

Thanks

Massimo
cut "pippo" out when using the address below.
---------------------------------------------
Massimo Pinto - Ph.D. Student

Sent via Deja.com http://www.deja.com/
Before you buy.

2. Is it Possible

3. Friend function template of class template

4. MS OS inferior without browser integration?

5. Syntax for declaring friend function template in class template

6. When are default arguments parsed?

7. Template Functions as Friends of Template Classes

8. Mac Prog Tutor Wanted (NYC)

9. template functions as restricted friends of template classes

10. Can template function be friend of non-template class?

11. How to make a general template class friend of a non-template class?

12. friend template class in template class