Connecting Tech Pros Worldwide Help | Site Map

Implementing operator<<

 
LinkBack Thread Tools Search this Thread
  #1  
Old January 17th, 2008, 01:55 PM
soy.hohe@gmail.com
Guest
 
Posts: n/a
Default Implementing operator<<

Hi all

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

template <class TStreamLogger& 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



  #2  
Old January 17th, 2008, 02:45 PM
Ondra Holub
Guest
 
Posts: n/a
Default Re: Implementing operator<<

On 17 Led, 15:34, soy.h...@gmail.com wrote:
Quote:
Hi all
>
I have a class StreamLogger which implements operator << in this way:
>
template <class TStreamLogger& 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.
  #3  
Old January 18th, 2008, 09:55 AM
James Kanze
Guest
 
Posts: n/a
Default Re: Implementing operator<<

On Jan 17, 3:34 pm, soy.h...@gmail.com wrote:
Quote:
I have a class StreamLogger which implements operator << in this way:
Quote:
template <class TStreamLogger& operator<<(const T& t)
{
<print the stuff using fstream, etc.>
return *this;
}
Quote:
It works perfectly, using it like:
m_logger << "My ID is " << getID() << "\n";
Quote:
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 = dest.stream() ;
if ( stream != NULL ) {
*stream << manip ;
}
return dest ;
}

inline OutputStreamWrapper const&
operator<<(
OutputStreamWrapper const&
dest,
std::ostream& (* manip)( std::ostream& ) )
{
std::ostream* stream = dest.stream() ;
if ( stream != 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ée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 

Bookmarks

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Popular Articles

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over 220,840 network members.