title: cout/cerr wrapper ostream with minimal effort
body: <p>I would like to learn C++ better (currently my C++ is limited to it's C subset *cough* ...), thus I decided to try to "C++ -ify" a useful logging function of mine from C to C++, which (I think) is best explained in code:</p>
  
  <pre class="lang-c prettyprint-override"><code>#include &lt;stdarg.h&gt;
  #include &lt;stdio.h&gt;
  
  enum msg_type {
      LOG_DBG,
      LOG_INF,
      LOG_WRN,
      LOG_ERR
  };
  
  int printf_log(enum msg_type mt, const char *fmt_string, ...)
  {
      va_list args;
      va_start(args, fmt_string);
  
      switch (mt) {
          case LOG_DBG:
              printf("[D] ");
              break;
          case LOG_INF:
              printf("[I] ");
              break;
          case LOG_WRN:
              printf("[W] ");
              break;
          case LOG_ERR:
              printf("[E] ");
              break;
          default:
              break;
      }
  
      int res = vprintf(fmt_string, args);
  
      va_end(args);
      return res;
  }
  
  int main()
  {
      int i = 0;
      printf_log(LOG_DBG, "i is %d\n", i);
      i++;
      printf_log(LOG_INF, "i is %d\n", i);
      i++;
      printf_log(LOG_WRN, "i is %d\n", i);
  }
  </code></pre>
  
  <p>This should output:</p>
  
  <pre class="lang-none prettyprint-override"><code>[D] i is 0
  [I] i is 1
  [W] i is 2
  </code></pre>
  
  <p>My idea of a C++ version of this is to have something like:</p>
  
  <pre class="lang-cc prettyprint-override"><code>#include &lt;log.h&gt;
  
  int main()
  {
      int i = 0;
      log::log(log::dbg)&lt;&lt;"i is " &lt;&lt; i &lt;&lt; "\n";
      i++;
      log::log(log::inf)&lt;&lt; "i is " &lt;&lt; i &lt;&lt; "\n";
      i++;
      log::log(log::wrn)&lt;&lt; "i is " &lt;&lt; i &lt;&lt; "\n";
  }
  </code></pre>
  
  <p>with the same result.</p>
  
  <p>I especially would like to avoid any parsing of the arguments (possibly except <code>log::inf</code> or similar) but just let them pass right onto <code>cout</code>.</p>
  
  <p>But I've not really an idea where to start and all things regarding this either expect more knowledge of C++ or want you to implement you whole own <code>streambuf</code> or similar.</p>
  
  <p>My idea is basically the same so I tried my best and this is the code that I've produced using different resources on the Internet:</p>
  
  <pre class="lang-cc prettyprint-override"><code>#include &lt;iostream&gt;
  
  using std::cout;
  class Log {
  
      public:
          enum msg_type {
              dbg =1,
              inf,
              wrn,
              err
          };
  
          Log(enum msg_type mt)
          {
              switch (mt) {
              case dbg:
                  cout &lt;&lt; "[D] ";
                  break;
              case inf:
                  cout &lt;&lt; "[I] ";
                  break;
              case wrn:
                  cout &lt;&lt; "[W] ";
                  break;
              case err:
                  cout &lt;&lt; "[E] ";
                  break;
              default:
                  break;
              }
          }
  
          template&lt;typename T&gt;
          const Log&amp; operator&lt;&lt;(const T&amp; t)
          {
  
              std::cout &lt;&lt; t;
              return *this;
          }
  };
  
  int main()
  {
      int i = 0;
      Log(Log::dbg)&lt;&lt; "i is " &lt;&lt; i++ &lt;&lt; "\n";
      Log(Log::inf)&lt;&lt; "i is " &lt;&lt; i++ &lt;&lt; "\n";
      Log(Log::inf)&lt;&lt; "i is " &lt;&lt; i++ &lt;&lt; "\n";
  }
  </code></pre>
  
  <p>Obviously it doesn't work but I've no idea on what the error messages try to tell me.</p>
  
  <p>G++:</p>
  
  <pre class="lang-none prettyprint-override"><code>main.cc: In function ‘int main()’:
  main.cc:46:34: error: passing ‘const Log’ as ‘this’ argument discards qualifiers [-fpermissive]
        Log(Log::dbg)&lt;&lt; "i is " &lt;&lt; i++ &lt;&lt; "\n";
                                    ^
  main.cc:35:14: note:   in call to ‘const Log&amp; Log::operator&lt;&lt;(const T&amp;) [with T = int]’
     const Log&amp; operator&lt;&lt;(const T&amp; t)
                ^
  main.cc:46:40: error: passing ‘const Log’ as ‘this’ argument discards qualifiers [-fpermissive]
        Log(Log::dbg)&lt;&lt; "i is " &lt;&lt; i++ &lt;&lt; "\n";
                                          ^
  main.cc:35:14: note:   in call to ‘const Log&amp; Log::operator&lt;&lt;(const T&amp;) [with T = char [2]]’
     const Log&amp; operator&lt;&lt;(const T&amp; t)
                ^
  </code></pre>
  
  <p>Clang:</p>
  
  <pre class="lang-none prettyprint-override"><code>main.cc:46:30: error: invalid operands to binary expression ('const Log' and 'int')
          Log(Log::dbg)&lt;&lt; "i is " &lt;&lt; i++ &lt;&lt; "\n";
          ~~~~~~~~~~~~~~~~~~~~~~~ ^  ~~~
  main.cc:35:14: note: candidate function not viable: 'this' argument has type
        'const Log', but method is not marked const
                  const Log&amp; operator&lt;&lt;(const T&amp; t)
                             ^
  1 error generated.
  </code></pre>
  
  <p>The easiest way of course would just doing a macro replacing any occurrence of my logging "fake-ostream" with eg. <code>cout &lt;&lt; [I] &lt;&lt;</code> but this is far less flexible.</p>
  
  <p>Does anyone have any ideas on how to do this correctly and can me hint to resources which describe this thoroughly?</p>
  
  <p>Any help is appreciated!</p>