On Aug 2, 10:04 pm, "kwikius" <a...@servocomm.freeserve.co.ukwrote:
"Darío Griffo" <dario.griffo.lis...@gmail.comwrote in message
news:b6**********************************@a1g2000h sb.googlegroups.com...
I'm having an error with this code
#include <iostream>
template < typename Tclass TestOpTemplate
{
public:
friend std::ostream& operator<< <>(std::ostream& os, const
TestOpTemplate<T>& m);
};
#include <iostream>
template < typename Tclass TestOpTemplate
{
public:
friend std::ostream& operator<<(std::ostream& os, const
TestOpTemplate<T>& m);
};
Be careful. That declares a non-template function as friend, so
he'll have to implement a non-template function for every
instance of TestOpTemplate.
I know that the current draft very explicitly provides for three
alternatives with regards to friend: a non-template, a template
for which only the corresponding specialization is a friend, and
a template for which all specializations are friend. For some
reason, however, I think that this is a recent clarification or
fix, and the compilers vary in what they actually implement
(except that all support a non-template as friend in more or
less the same manner). Anyway, my "standard" solution is to
define a public member function print(), and then define the
operator<< inline, which just calls it, e.g.:
template< typename T >
class TestOpTemplate
{
public:
void print( std::ostream& ) ;
friend std::ostream& operator<<(
std::ostream& dest,
TestOpTemplate< T const& obj )
{
obj.print( dest ) ;
return dest ;
}
} ;
Since the friend function is defined each time the template is
specialized, it doesn't matter that it's not a template; you get
a new non-template function for each type.
Of course, in practice, the case comes up fairly often, so I've
moved these functions down into a templated base class, so it's
sufficient that my class derives from it, e.g.:
template< typename T >
struct IOStreamOperators
{
friend std::ostream& operator<<(
std::ostream& dest,
T const& obj )
{
obj.print( dest ) ;
return dest ;
}
friend std::istream& operator>>(
std::istream& source,
T& obj )
{
obj.scan( source ) ;
return source ;
}
} ;
template< typename T >
class TestOpTemplate
: public IOStreamOperators< TestOpTemplate < T
{
public:
void print( std::ostream& ) ;
} ;
And in case it isn't obvious:
-- the only reason for the friend in these cases is to allow
you to define the non-member function in the class
definition, and
-- if you never used one of the functions in IOStreamOperators,
it won't be instantiated, so you won't get an error if the
member function it calls isn't present.
--
James Kanze (GABI Software) email:ja*********@gmail.com
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