title: Inheriting from std::basic_streambuf to write to a socket
body: <p>I would like to write a logging library of my own that provides abstraction for wherever the log entries are sent to.</p>
  
  <p>The IO library of C++ already provides that kind of abstraction with <code>std::stringstream</code> and <code>std::fstream</code>. I would also like to be able to read/write from/to a socket.</p>
  
  <p>I read that the proper way of extending the standard library is to inherit from <code>std::basic_streambuf</code>. What I don't understand is, if inheriting from <code>std::basic_streambuf</code> like <code>std::basic_filebuf</code> does, where is the need for the <code>std::ifsream</code>, <code>std::ofstream</code> and <code>std::fstream</code> classes ? Can't I just replace the buffer of some stream with a instance of a subclass of <code>std::basic_streambuf</code> which outputs where I want it to ?</p>
  
  <p>So far I have done the following, but I really am not sure about what I'm doing. Is the following design correct ?</p>
  
  <pre><code>template&lt; typename char_type, typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_sock_streambuf : public std::basic_streambuf&lt; char_type, traits_type &gt;
  {
  public:
  
      basic_sock_streambuf()
      {
  
      }
  
      ~basic_sock_streambuf()
      {
  
      }
  
      int overflow (int c = EOF)
      {
          fputc( c, stdout ); // Temporary.
          return traits_type::to_int_type( c );
      }
  
      int underflow()
      {
          return fgetc( stdout ); // Temporary.
      }
  
      int sync()
      {
          return 0;
      }
  };
  
  template&lt; typename char_type, typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_isockstream : public std::basic_istream&lt; char_type, traits_type &gt;
  {
  };
  
  template&lt; typename char_type, typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_osockstream : public std::basic_ostream&lt; char_type, traits_type &gt;
  {
  };
  
  template&lt; typename char_type, typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_socktream : public basic_isockstream&lt; char_type, traits_type &gt;, public basic_osockstream&lt; char_type, traits_type &gt;
  {
  private:
  
      typedef basic_isockstream&lt; char_type, traits_type &gt; iparent;
  
      typedef basic_osockstream&lt; char_type, traits_type &gt; oparent;
  
      basic_sock_streambuf&lt; char_type, traits_type &gt; sock_sb;
  
      std::basic_streambuf&lt; char_type, traits_type &gt; * old_isb;
  
      std::basic_streambuf&lt; char_type, traits_type &gt; * old_osb;
  
  public:
  
      basic_socktream()
      {
          old_isb = iparent::rdbuf( &amp; sock_sb );
          old_osb = oparent::rdbuf( &amp; sock_sb );
      }
  
      ~basic_socktream() throw()
      {
          iparent::rdbuf( old_isb );
          oparent::rdbuf( old_osb );
      }
  };
  </code></pre>
  
  <p>EDIT : Code updated based on answers :</p>
  
  <pre><code>template&lt;
      typename char_type,
      typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_sockbuf :
      public std::basic_streambuf&lt; char_type, traits_type &gt;
  {
  public:
  
      basic_sockbuf()
      {
      }
  
      ~basic_sockbuf()
      {
      }
  
      int overflow( int c = EOF )
      {
          fputc( c, stdout ); // Temporary.
          return traits_type::to_int_type( c );
      }
  
      int underflow()
      {
          return fgetc( stdout ); // Temporary.
      }
  
      int sync()
      {
          return 0;
      }
  };
  
  template&lt;
      typename char_type,
      typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_isockstream :
      public std::basic_istream&lt; char_type, traits_type &gt;
  {
  private:
  
      typedef std::basic_istream&lt; char_type, traits_type &gt; parent;
  
      basic_sockbuf&lt; char_type, traits_type &gt; buffer;
  
  public:
  
      basic_isockstream() :
          std::basic_istream&lt; char_type, traits_type &gt;::basic_istream(),
          buffer()
      {
          init( &amp; buffer );
      }
  };
  
  template&lt;
      typename char_type,
      typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_osockstream :
      public std::basic_ostream&lt; char_type, traits_type &gt;
  {
  private:
  
      basic_sockbuf&lt; char_type, traits_type &gt; buffer;
  
  public:
  
      basic_osockstream() :
          std::basic_ostream&lt; char_type, traits_type &gt;::basic_istream(),
          buffer()
      {
          init( &amp; buffer );
      }
  };
  
  template&lt;
      typename char_type,
      typename traits_type = std::char_traits&lt; char_type &gt; &gt;
  class basic_socktream :
      public std::basic_iostream&lt; char_type, traits_type &gt;,
      public basic_sockbuf&lt; char_type, traits_type &gt;
  {
  private:
  
      basic_sockbuf&lt; char_type, traits_type &gt; buffer;
  
  public:
  
      basic_socktream() :
          std::basic_iostream&lt; char_type, traits_type &gt;::basic_iostream(),
          buffer()
      {
          std::basic_iostream&lt; char_type, traits_type &gt;::init( &amp; buffer );
      }
  };
  </code></pre>