Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Special Interest Groups
  3. C++ Gurus
  4. [Solved] Problem defining a std::endl manipulator for a custom class
Forum Updated to NodeBB v4.3 + New Features

[Solved] Problem defining a std::endl manipulator for a custom class

Scheduled Pinned Locked Moved C++ Gurus
6 Posts 3 Posters 4.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JohanSolo
    wrote on 9 May 2011, 07:51 last edited by JohanSolo 4 Aug 2015, 06:57
    #1

    Hi gurus,

    I've implemented a logging class that is responsible for producing output to std output, adding colors and name of the caller class, and has some output levels defined. I'm on Fedora 14 32bits, using GCC 4.5.1 with glibc 2.13.

    Here's the header file :

    #include <string>
    #include <iomanip>
    #include <sstream>
    
    #include <map>
    
    #include "CColor.h" // Color codes
    
    enum DebugLevelType
      {
        ALL, /**< Shows everything */
        MEM, /**< Ultra detailed debugging */
        DEBUG, /**< Debugging message */
        LFUNC, /**< Function output in loops */
        LINFO, /**< Info message in loops */
        FUNC, /**< Function message */
        INFO, /**< General info */
        BLANK, /**< Equivalent of std::cout */
        PROGRESS, /**< - */
        RELEASE, /**< Information that would go in a logfile */
        WARN, /**<Warning, beeps */
        ERR, /**< Critical failure message, beeps also */
        OFF /**< No output */
      };
    
    class MessageStream
    {
     public:
      MessageStream( const DebugLevelType& level, const string& source = "" );
      MessageStream( const MessageStream& flot );
      virtual ~MessageStream();
      std::ostringstream& stream();
      const DebugLevelType& currentLevel() const;
      const DebugLevelType& instanceLevel() const;
      static void setUseColour( const bool& useColour );
      static const bool& useColour();
      const bool& isActive() const;
      MessageStream& doOutput();
      MessageStream& flush();
      MessageStream& operator<<( const DebugLevelType& level );
      std::string Source;
      std::ostringstream Stream;
      DebugLevelType CurrentLevel;
      DebugLevelType InstanceLevel;
      static bool UseColour;
      bool IsActive;
    
     private:
      static const std::map< DebugLevelType, CColor > Decorations;
    
      static const std::map< DebugLevelType, std::string > Textes;
    
      void activate();
      void deactivate();
    };
    
    MessageStream& endmsg( MessageStream& flot );
    
    template< typename T >
    MessageStream& operator<<( MessageStream& flot, const T& arg )
    {
      flot.stream() << arg;
      return flot;
    }
    

    As the class doesn't inherit from any output stream class, I had to define the operator<< template, which works fine. The endmsg function is supposed to act like std::endl. The code is :

    MessageStream& endmsg( MessageStream& flot )
    {
      return flot.doOutput();
    }
    
    MessageStream& MessageStream::doOutput()
    {
      try
        {
          if ( isActive() )
            {
              if ( useColour() )
                cout << Decorations.find( CurrentLevel ) -> second . colorCode();
              if ( NiveauCourant != BLANK )
                cout << setw( 20 ) << left << Source << setw( 10 )
                        << left << Textes.find( CurrentLevel ) -> second;
              cout << Stream.str();
             if ( useColour() )
               cout << "\033[0m"; // resets the color to default
           cout << endl;
         }
    
         Stream.str( "" );
       }
       catch( exception& e )
       {
          cerr << "Exeption : " << e.what() << endl;
       }
      return *this;
    }
    

    Now, when I use a stupid example to perform some tests, I do this :

    MessageStream Debug( DEBUG, "StupidTest" );
    
    Debug << "Some debug statement" << endmsg;
    

    I expect the output to be like "StupidTest DEBUG Some debug statement", but the output I get is "StupidTest DEBUG Some debug statement1", without any newline. I understand that my template tries to use "endmsg" as a regular variable, and puts a '1'. How can I get this to work...?

    I tried to make MessageStream inherit from std::ostringstream, but

    1. it doesn't work either
    2. the std::left and std::setw( ) don't work properly.

    Is there a way to prevent the MessageStream instance to use the template when endmsg is added to the stream output? If not, how should I write the endmsg function?

    Thanks in advance,
    johan

    `They did not know it was impossible, so they did it.'
    -- Mark Twain

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on 9 May 2011, 07:59 last edited by
      #2

      Couldn't you make endmsg a type, and specialize your MessageStream& operator<< for that type?

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JohanSolo
        wrote on 9 May 2011, 08:03 last edited by
        #3

        I guess I can, I didn't think about it. I basically looked at "this code":http://lhcb-release-area.web.cern.ch/LHCb-release-area/DOC/analysis/releases/latest/doxygen/dd/d15/_msg_stream_8h_source.html and tried to remove the stuff I don't need.

        I'll test your suggestion, thanks!

        `They did not know it was impossible, so they did it.'
        -- Mark Twain

        1 Reply Last reply
        0
        • K Offline
          K Offline
          koahnig
          wrote on 9 May 2011, 08:33 last edited by
          #4

          Hi Johan,

          I have noted in your code that you reference MessageStream. However, the doOutput method is writing the endl simply to cout respectively to cerr in case of an error.
          That looks strange to me.

          Can you elaborate a little on that part?

          I would have expected that you write the endl to MessageStream.

          Vote the answer(s) that helped you to solve your issue(s)

          1 Reply Last reply
          0
          • J Offline
            J Offline
            JohanSolo
            wrote on 9 May 2011, 08:53 last edited by
            #5

            [quote author="koahnig" date="1304930013"]Hi Johan,

            I have noted in your code that you reference MessageStream. However, the doOutput method is writing the endl simply to cout respectively to cerr in case of an error.
            That looks strange to me.

            Can you elaborate a little on that part?

            I would have expected that you write the endl to MessageStream.[/quote]

            Hi,

            I'm not sure to understand your question. The MessageStream class itself is no output stream, it is designed in such a (bad?) way that you need to call doOutput in order to display it in your terminal. As long as you don't call doOutput you are just filling up the Stream object of your MessageStream instance, but no output is produced. As long as there is no error the message is then printed to std::cout (against which I guess you have no objection), but I usually do error report on std::cerr that's all.

            As mentionned in a previous post, this class was inspired by a class used in the LHCb experiment, class which was coded by people much smarter than me, and I didn't question their choice of implementation (which may be a wrong idea).

            @ Andre : thanks again, you made my day!!

            `They did not know it was impossible, so they did it.'
            -- Mark Twain

            1 Reply Last reply
            0
            • K Offline
              K Offline
              koahnig
              wrote on 9 May 2011, 08:58 last edited by
              #6

              Thanks for clarification. The naming is a little misleading then. That made me stumbling when trying to understand. Anyhow, I am happy that your problem has been solved.

              Vote the answer(s) that helped you to solve your issue(s)

              1 Reply Last reply
              0

              1/6

              9 May 2011, 07:51

              • Login

              • Login or register to search.
              1 out of 6
              • First post
                1/6
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved