Re: Problem with operator << and templates
On Aug 2, 10:04 pm, "kwikius" <a...@servocomm.freeserve.co.uk> wrote:
"Dar=EDo Griffo" <dario.griffo.lis...@gmail.com> wrote in message
news:b6837608-78d8-4bc4-bb0e-0bafc40de37b@a1g2000hsb.googlegroups.com...
I'm having an error with this code
#include <iostream>
template < typename T> class TestOpTemplate
{
public:
friend std::ostream& operator<< <>(std::ostream& os, const
TestOpTemplate<T>& m);
};
#include <iostream>
template < typename T> class 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:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34