Существует ли тип контейнера произвольного доступа, который принимает предварительно заполненный и предварительно выделенный буфер? - PullRequest
10 голосов
/ 28 июля 2011

Я собираюсь написать что-то сам, так как я не нашел то, что искал, но решил, что мне следует спросить толпу, прежде чем погрузиться.

  • Есть ли повышение или случайность?Доступ к типу контейнера, который позволяет передавать предварительно заполненный буфер?

Мнимый (?) тип контейнера будет работать примерно так:

  const int blobSize = unpackBlobSize( msg );
  int *     blob     = unpackBlobData( msg );

  SpecialVector<int> mySpecialIntVector( blob, blobSize );

По сути, я взаимодействую со старой библиотекойс необработанными указателями на буферы в стиле c, но хотел бы использовать семантику контейнера в стиле C ++ без необходимости выполнения шага копирования.Я хотел бы иметь std :: vector плюс предварительно выделенный и предварительно заполненный буферный конструктор и минус resize.

Libeigen имеет такую ​​функциональность с Eigen :: Map, которая допускает такие вещи, как:

  int array[9];
  for(int i = 0; i < 9; ++i) 
      array[i] = i;
  stl::cout << Eigen::Map<Eigen::Matrix3i>(array) << stl::endl;

Кто-нибудь знает шаблон boost или stl, который охватывает эти ограничения?

Ответы [ 3 ]

8 голосов
/ 28 июля 2011

Исходя из комментария Денниса Цикенфуза, я посмотрел на Boost.range, похоже, предлагает идеальное решение:

  #include <boost/range.hpp>
  #include <boost/foreach.hpp>
  #include <iostream>

  int main()
  {
    const int blobSize = 100;
    int blob[blobSize];

    for( int i = 0; i < blobSize; ++i )
      blob[i] = i;

    boost::iterator_range<int*> blobPsudoContainer( blob, blob + blobSize );

    BOOST_FOREACH( int & i, blobPsudoContainer )
      i = i + 1;

    std::cout << "Size is:" << blobPsudoContainer.size() << "\n";
    std::cout << "value at 0 is:" << blobPsudoContainer[0] << "\n";
    return 0;
  }

Спасибо Деннис!:)

4 голосов
/ 28 июля 2011

Нет ничего, как вы хотите, это просто недостаток языка. Если вы удовлетворены тем, что распределитель статически угадывает ожидаемое максимальное максимальное количество элементов, вы можете просто встроить обычный массив C в распределитель и отложить его как можно дольше; обычно это называется автоматическим буфером.


Старый ответ:

Все стандартные контейнеры библиотеки позволяют вам указывать распределитель. Вы можете сделать распределитель буфера.

0 голосов
/ 05 августа 2011

Я решил опубликовать собственное решение, которое в итоге использовал для потомков, и в случае, если кому-то будет любопытно или есть какие-либо комментарии. Пожалуйста, простите за жесткое форматирование; Это было избавление от горизонтального свитка.

Дайте мне знать в разделе комментариев, если вы используете это. Мне было бы любопытно услышать, было ли это полезно кому-то еще.

Нам понадобятся следующие заголовки:

 #include <boost/range/iterator_range.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_array.hpp>
 #include <vector>

Помощник для привязки к существующему пересчитанному объекту

 template<typename RefCountedTypeT>
 struct RefCountLinkFunctor
 {
   public:
     RefCountLinkFunctor( const RefCountedTypeT & ptr ) 
       : m_ptr(ptr) 
     { 
       &RefCountedTypeT::use_count; // try to check if refcounted
      } 

      template<typename T> void operator()(T*) {}

   protected:
     RefCountedTypeT m_ptr;
 };

А потом:

 template< typename DataT >
 class DataRange : public boost::iterator_range< DataT * >
 {
 public:
   typedef boost::iterator_range< DataT * >    ParentType;
   typedef DataRange< DataT >                  OwnType;
   typedef DataT                               DataType;
   typedef boost::iterator_range< DataType * > Range;
   typedef boost::shared_ptr< OwnType >        Ptr;
   typedef std::vector<DataType>               DataVector;
   typedef boost::shared_ptr<DataVector>       DataVectorPtr;

   static Ptr allocateShared( std::size_t size )
   {
     typedef boost::shared_array<DataType>         DataSharedArray;
     typedef RefCountLinkFunctor<DataSharedArray>  Deleter;

     DataSharedArray   dataArray( new DataType[size] );
     Deleter           deleter( dataArray );

     DataT * begin = dataArray.get();
     DataT * end   = begin + size;

     return Ptr( new OwnType(begin, end), deleter);
   }

   template< typename RefCountedT >
   static Ptr 
   makeShared( DataType * begin, DataType * end, const RefCountedT & refObj )
   {
     RefCountLinkFunctor< RefCountedT >  deleter( refObj );
     return Ptr( new OwnType(begin, end), deleter );
   }

   template< typename RefCountedT, typename InDataT >
   static Ptr 
   makeShared( DataVector & data, const RefCountedT & refObj )
   {
     RefCountLinkFunctor< RefCountedT >  deleter( refObj );

     DataType * begin = &data.front();
     DataType * end   = begin + data.size();

     return makeShared( begin, end, deleter );
   }

   static Ptr makeShared( const DataVectorPtr & data )
   {
     typedef boost::shared_ptr< std::vector<DataType> > InputVectorPtr;

     RefCountLinkFunctor< InputVectorPtr >  deleter( data );

     DataType * begin = &data->front();
     DataType * end   = begin + data->size();

     return makeShared( begin, end, deleter );
   }

 protected:
     DataRange( DataType * begin, DataType * end ) : ParentType( begin, end ){}

};
...