Implementing operator<<



 DEVELOP > c-Plus-Plus > Implementing operator<<

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > c-Plus-Plus
User: ""
Date: 17 Jan 2008 08:34:38 AM
Object: Implementing operator<<
Hi all
I have a class StreamLogger which implements operator << in this way:
template <class T> StreamLogger& operator<<(const T& t)
{
<print the stuff using fstream, etc.>
return *this;
}
It works perfectly, using it like:
m_logger << "My ID is " << getID() << "\n";
but for some reason it does not compile this code:
m_logger << std::endl;
It gives the following error:
--------------------------------------------------------------------------------
..\src\Dealer.cpp(70) : error C2678: binary '<<' : no operator found
which takes a left-hand operand of type 'StreamLogger' (or there is no
acceptable conversion)
C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include
\afx.h(1428): could be 'CDumpContext &operator <<(CDumpContext
&,ATL::CTimeSpan)'
....
--------------------------------------------------------------------------------
Could you guys help me understand why it doesn't compile? (because I
dont have a clue...)
Thanks!!!
Jorge
.

User: "Ondra Holub"

Title: Re: Implementing operator<< 17 Jan 2008 09:38:43 AM
On 17 Led, 15:34,
wrote:

Hi all

I have a class StreamLogger which implements operator << in this way:

template <class T> StreamLogger& operator<<(const T& t)
{
<print the stuff using fstream, etc.>

return *this;

}

It works perfectly, using it like:
m_logger << "My ID is " << getID() << "\n";

but for some reason it does not compile this code:
m_logger << std::endl;

It gives the following error:
--------------------------------------------------------------------------------
.\src\Dealer.cpp(70) : error C2678: binary '<<' : no operator found
which takes a left-hand operand of type 'StreamLogger' (or there is no
acceptable conversion)
C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include
\afx.h(1428): could be 'CDumpContext &operator <<(CDumpContext
&,ATL::CTimeSpan)'
...
--------------------------------------------------------------------------------

Could you guys help me understand why it doesn't compile? (because I
dont have a clue...)

Thanks!!!

Jorge

You have to do following steps:
1. Create your own manipulator in std:
namespace std
{
StreamLogger& endl(StreamLogger& s)
{
// Here do what manipulator should do
return s;
}
StreamLogger& hex(StreamLogger& s)
{
// Here do what manipulator should do
return s;
}
// Define all standard manipulators which do not have parameters
// ...
}
2. Overload operator<< to accept function of the same type as
manipulator is:
StreamLogger& operator<<(StreamLogger& s, StreamLogger& (*manip)
(StreamLogger& s))
{
return manip(s);
}
3. Use your manipulator in usual way:
StreamLogger sl;
sl << std::endl;
You should define all standard manipulators for your StreamLogger to
have standard interface. Do not ask me how to support anipulators with
parameters. I know it is (of course) possible, but I do not remember
the solution.
.

User: "James Kanze"

Title: Re: Implementing operator<< 18 Jan 2008 04:46:03 AM
On Jan 17, 3:34 pm,
wrote:

I have a class StreamLogger which implements operator << in this way:
template <class T> StreamLogger& operator<<(const T& t)
{
<print the stuff using fstream, etc.>
return *this;
}
It works perfectly, using it like:
m_logger << "My ID is " << getID() << "\n";
but for some reason it does not compile this code:
m_logger << std::endl;

The problem is that std::endl is also a template. The actual
instantiation of the template will be determined by the type of
the parameter of operator<<, and the type of the parameter of
operator<< will be determined by the type of the argument, i.e.
the type of the instantiated std::endl template.
You'll run into this problem any time you try to output
something that is an uninstantiated template (or an overloaded
function)---in practice, that means the standard manipulators.
The solution is to add a non-template overload to catch
them---template argument deduction fails for your function
template, but the non-template overloads are still considered.
Something like:
inline OutputStreamWrapper const&
operator<<(
OutputStreamWrapper const&
dest,
std::ios_base& (* manip)( std::ios_base& ) )
{
std::ostream* stream =3D dest.stream() ;
if ( stream !=3D NULL ) {
*stream << manip ;
}
return dest ;
}
inline OutputStreamWrapper const&
operator<<(
OutputStreamWrapper const&
dest,
std::ostream& (* manip)( std::ostream& ) )
{
std::ostream* stream =3D dest.stream() ;
if ( stream !=3D NULL ) {
*stream << manip ;
}
return dest ;
}
seems to be sufficient. (I note that in my code, I've also got
a non-template overload for char const*. I don't remember why;
whether there is some fundamental problem due to the actual type
of the string literal being char const[], or if it is just a
work-around for a compiler bug somewhere. In general, however:
most of the time you encounter a problem, it will be because
template argument deduction isn't able to handle the case, and
an explicit non-template overload will do the trick.)
--
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
.


  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.1232     pg.940     pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER