Implementing operator<<

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • soy.hohe@gmail.com

    #1

    Implementing operator<<

    Hi all

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

    template <class TStreamLogger& operator<<(cons t 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.c pp(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\inc lude
    \afx.h(1428): could be 'CDumpContext &operator <<(CDumpConte xt
    &,ATL::CTimeSpa n)'
    ....
    --------------------------------------------------------------------------------

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


    Thanks!!!

    Jorge


  • Ondra Holub

    #2
    Re: Implementing operator&lt;&lt ;

    On 17 Led, 15:34, soy.h...@gmail. com wrote:
    Hi all
    >
    I have a class StreamLogger which implements operator << in this way:
    >
    template <class TStreamLogger& operator<<(cons t 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.cp p(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\inc lude
    \afx.h(1428): could be 'CDumpContext &operator <<(CDumpConte xt
    &,ATL::CTimeSpa n)'
    ...
    --------------------------------------------------------------------------------
    >
    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(StreamLogg er& s)
    {
    // Here do what manipulator should do
    return s;
    }

    StreamLogger& hex(StreamLogge r& 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<<(Stre amLogger& 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.

    Comment

    • James Kanze

      #3
      Re: Implementing operator&lt;&lt ;

      On Jan 17, 3:34 pm, soy.h...@gmail. com wrote:
      I have a class StreamLogger which implements operator << in this way:
      template <class TStreamLogger& operator<<(cons t 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 OutputStreamWra pper const&
      operator<<(
      OutputStreamWra pper const&
      dest,
      std::ios_base& (* manip)( std::ios_base& ) )
      {
      std::ostream* stream = dest.stream() ;
      if ( stream != NULL ) {
      *stream << manip ;
      }
      return dest ;
      }

      inline OutputStreamWra pper const&
      operator<<(
      OutputStreamWra pper 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.kan ze@gmail.com
      Conseils en informatique orientée objet/
      Beratung in objektorientier ter Datenverarbeitu ng
      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

      Comment

      Working...