title: Boost.Asio - Multiple buffers with custom buffer
body: <p>I'm writing a kind of tcp server. I'm using Boost.Asio, with <a href="http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp" rel="nofollow noreferrer">shared_const_buffer</a>.</p>
  
  <p>Now I have to write multiple buffers. So I write like this:</p>
  
  <pre><code>std::vector&lt;shared_const_buffer&gt; bufs;
  bufs.push_back(buf1);
  bufs.push_back(buf2);
  ...
  boost::asio::async_write(*pSock, bufs, [] { ... });
  </code></pre>
  
  <p>However, I can see an error.</p>
  
  <blockquote>
    <p>d:\boost_1_56_0\boost\asio\detail\consuming_buffers.hpp(175): error C2679: 이항 '=' : 오른쪽 피연산자로 'shared_const_buffer' 형식을 사용하는 연산자가 없거나 허용되는 변환이 없습니다.</p>
  </blockquote>
  
  <p>Well, my Visual Studio is not English version >o&lt; Here's my translation</p>
  
  <blockquote>
    <p>d:\boost_1_56_0\boost\asio\detail\consuming_buffers.hpp(175): error C2679: binary operator '=' : there's no operator or permissible conversion which use <code>shared_const_buffer</code> type as right-hand-side.</p>
  </blockquote>
  
  <p>I'm not sure that my translation is correct, but I think you can get a point. Anyway, I saw <code>boost\asio\detail\consuming_buffers.hpp(175)</code> to figure out the problem.</p>
  
  <pre><code>if (!at_end_)
  {
    first_ = *buffers_.begin(); // &lt;-- here's error point
    ++begin_remainder_;
  }
  </code></pre>
  
  <p>So I tried adding casting operator into <code>shared_const_buffer</code>, and it works magically.</p>
  
  <p>Here's my <a href="https://stackoverflow.com/help/mcve">mcve</a></p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;memory&gt;
  
  #include &lt;boost/asio.hpp&gt;
  
  using boost::asio::ip::tcp;
  
  class shared_const_buffer
  {
  private:
      std::shared_ptr&lt;std::vector&lt;char&gt; &gt; m_pData;
      boost::asio::const_buffer m_buffer;
  
  public:
      explicit shared_const_buffer(const std::vector&lt;char&gt; &amp;data)
          : m_pData { std::make_shared&lt;std::vector&lt;char&gt; &gt;(data) }
          , m_buffer { boost::asio::buffer(*m_pData) }
      {
  
      }
  
      typedef boost::asio::const_buffer value_type;
      typedef const boost::asio::const_buffer *const_iterator;
      const boost::asio::const_buffer *begin() const { return &amp;m_buffer; }
      const boost::asio::const_buffer *end() const { return &amp;m_buffer + 1; }
  
      // it'll work if you uncomment this line.
      //operator const boost::asio::const_buffer &amp;() const { return *begin(); }
  };
  
  void run_accept(boost::asio::io_service &amp;iosrv, tcp::acceptor &amp;acpt);
  
  int main()
  {
      boost::asio::io_service iosrv;
  
      tcp::acceptor acpt(iosrv, tcp::endpoint(tcp::v4(), 12345));
      run_accept(iosrv, acpt);
  
      iosrv.run();
  }
  
  void run_accept(boost::asio::io_service &amp;iosrv, tcp::acceptor &amp;acpt)
  {
      auto pSock = std::make_shared&lt;tcp::socket&gt;(iosrv);
      acpt.async_accept(*pSock,
          [&amp;, pSock](const boost::system::error_code &amp;ec) {
              run_accept(iosrv, acpt);
  
              std::vector&lt;shared_const_buffer&gt; bufs;
              bufs.push_back(shared_const_buffer({ 'a', 'b', 'c', 'd' }));
              bufs.push_back(shared_const_buffer({ 'e', 'f', 'g', 'h' }));
  
              boost::asio::async_write(*pSock, bufs,
                  [pSock](const boost::system::error_code &amp;ec, size_t size) {
                      pSock-&gt;close();
                  });
          });
  }
  </code></pre>
  
  <p>However, I can't know <em>why</em> it doesn't work. <a href="http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/buffer.html#boost_asio.reference.buffer.buffers_and_scatter_gather_i_o" rel="nofollow noreferrer">According to documentation</a>,</p>
  
  <blockquote>
    <p><strong>Buffers and Scatter-Gather I/O</strong></p>
    
    <p>To read or write using multiple buffers (i.e. scatter-gather I/O), multiple buffer objects may be assigned into a container that supports the MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:</p>
  </blockquote>
  
  <pre><code>char d1[128];
  std::vector&lt;char&gt; d2(128);
  boost::array&lt;char, 128&gt; d3;
  
  boost::array&lt;mutable_buffer, 3&gt; bufs1 = {
    boost::asio::buffer(d1),
    boost::asio::buffer(d2),
    boost::asio::buffer(d3) };
  bytes_transferred = sock.receive(bufs1);
  
  std::vector&lt;const_buffer&gt; bufs2;
  bufs2.push_back(boost::asio::buffer(d1));
  bufs2.push_back(boost::asio::buffer(d2));
  bufs2.push_back(boost::asio::buffer(d3));
  bytes_transferred = sock.send(bufs2);
  </code></pre>
  
  <p>Also <a href="http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp" rel="nofollow noreferrer">documentation</a> says it's enough with these 5 line to satisfy "ConstBufferSequence".</p>
  
  <pre><code>// Implement the ConstBufferSequence requirements.
  typedef boost::asio::const_buffer value_type;
  typedef const boost::asio::const_buffer* const_iterator;
  const boost::asio::const_buffer* begin() const { return &amp;buffer_; }
  const boost::asio::const_buffer* end() const { return &amp;buffer_ + 1; }
  </code></pre>
  
  <p>What did I miss? I'm using Visual Studio 2013 Update 3 and boost 1.56.0.</p>