Повышение asio ConstBufferSequence - шаблоны C ++ - PullRequest
7 голосов
/ 01 июня 2011

Я надеюсь получить некоторые рекомендации относительно шаблонов C ++. Я использовал библиотеку boost::asio для связи по TCP. До сих пор я использовал контейнеры для хранения, встроенные в библиотеку boost :: asio. Например:

boost::array<char, 128> buf;
boost::system::error_code error;
size_t len = socket.read_some(boost::asio::buffer(buf), error);

Чтобы читать из сокета, я просто обертываю буфер типа boost::asio::buffer вокруг моего boost::array объекта. Это прекрасно работает, но теперь я бы хотел работать в обратном направлении. То есть я хотел бы записать обратно в сокет, извлекая данные из некоторых пользовательских классов хранения, которые у меня уже есть. У меня вопрос: как понять требования к типу шаблона, которые необходимо обернуть с помощью boost :: asio :: buffer или, в более общем смысле, тип параметра, указанный в:

template<typename ConstBufferSequence>
std::size_t send(   
   const ConstBufferSequence & buffers
);

В API перечислены требования ConstBufferSequence , но я не могу понять, как это сделать. Может кто-нибудь помочь мне понять? Какие методы нужно будет предоставить типу, который я хочу передать функции send?

Ответы [ 2 ]

6 голосов
/ 01 июня 2011

boost::asio::buffer возвращает объекты, реализующие концепции ConstBufferSequence и MutableBufferSequence; вы не будете их реализовывать. Конкретные типы, которые вам разрешено передавать на buffer, перечислены здесь .

1 голос
/ 22 марта 2012

Хотя boost :: asio :: buffer работает нормально, если у вас есть непрерывный набор байтов в памяти, который вы хотите использовать в качестве буфера, если вы используете scatter / collect I / O - или, в частности, если вы используетеиспользуя сборку (чтение разброса встречается гораздо реже), вам нужен объект, который ведет себя как ConstBufferSequence.

[Если бы Concepts превратил его в стандарт [sigh], вам нужен объект, реализующий концепцию ConstBufferSequence]

Вот фрагмент кода из класса Codecs :: DataDestinationQuickFAST (http :: //www.quickfast.org), который реализует ConstBufferSequence:

class DataDestination
{
  /// @brief Support for asio gather writes: forward iterator through buffers
  ///
  /// The intent is for DataDestination to conform to the asio::ConstBufferSequence concept.
  /// This would allow it to be passed directly to the asio::write(v)
  /// Note the implication that if asynch writes are used the DataDestination must
  /// remain intact until the write completes.
  class const_iterator
  {
  public:
    /// @brief construct an iterator pointing into a DataDestination
    /// @param destination is the buffer-container
    /// @param position is the starting position for the iterator.
    const_iterator(const DataDestination & destination, size_t position)
      : destination_(destination)
      , position_(position)
    { 
    }
     /// @brief Point iterator to next buffer (preincrement)
    const_iterator & operator ++()
    {
      if(position_ < destination_.size())
      {
        ++position_;
      }
      return *this;
    }

    /// @brief Point iterator to next buffer (postincrement)
    const_iterator operator ++(int)
    {
      const_iterator result(*this);
      if(position_ < destination_.size())
      {
        ++position_;
      }
      return result;
    }

    /// @brief dereference the iterator to find the actual buffer
    boost::asio::const_buffer operator * () const
    {
      const WorkingBuffer & buffer(destination_[position_]);
      return boost::asio::const_buffer(buffer.begin(), buffer.size());
    }

    /// @brief dereference the iterator to find the actual buffer
    boost::asio::const_buffer operator -> () const
    {
      const WorkingBuffer & buffer(destination_[position_]);
        return boost::asio::const_buffer(buffer.begin(), buffer.size());
    }

    /// @brief compare iterators.
    /// @param rhs is the iterator to which this should be compared.
    bool operator == (const const_iterator & rhs) const
    {
      return position_ == rhs.position_;
    }

    /// @brief compare iterators.
    /// @param rhs is the iterator to which this should be compared.
    bool operator != (const const_iterator & rhs) const
    {
      return position_ != rhs.position_;
    }
  private:
    const_iterator & operator=(const_iterator &); // no autogenerated assignment

  private:
    const DataDestination & destination_;
    size_t position_;
  };

  /// @brief return iterator pointing to the first buffer.
  const_iterator begin()const
  {
    return const_iterator(*this, 0);
  }

  /// @brief return iterator pointing past the last buffer
  const_iterator end() const
  {
    return const_iterator(*this, used_);
  }
};
...