Существует ли тип контейнера с произвольным доступом, который принимает предварительно заполненный и предварительно выделенный буфер?
Я собираюсь написать что-то сам, так как я не нашел то, что искал, но решил, что я должен спросить толпу перед погружением.
- Есть ли тип контейнера с буфером или stl произвольным доступом, который позволяет передавать в предварительно заполненный буфер?
Мнимая (?) тип контейнера будет работать примерно так:
const int blobSize = unpackBlobSize( msg );
int * blob = unpackBlobData( msg );
SpecialVector<int> mySpecialIntVector( blob, blobSize );
В основном я взаимодействую с старой библиотекой с исходными указателями-буферами c-style, но хотел бы использовать семантику контейнера стиля С++, не требуя этапа копирования. Я бы надеялся, что это std::vector плюс предварительно выделенный и предварительно заполненный конструктор буфера и, минус изменение размера.
У 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, который охватывает эти ограничения?
Ответы
Ответ 1
Переходя от комментария Денниса Zickenfoose, я посмотрел 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;
}
Спасибо Деннис!:)
Ответ 2
Нет ничего подобного, это просто недостаток языка. Если вы были удовлетворены тем, что распределитель статически угадал ожидаемый максимальный счетчик элементов, вы можете просто вставить обычный массив C внутри распределителя и отложить до него как можно дольше; это обычно называют автоматическим буфером.
Старый ответ:
Все стандартные контейнеры библиотеки позволяют указать распределитель. Вы можете сделать распределитель буфера.
Ответ 3
Я решил, что опубликую пользовательское решение, которое я использовал для потомков, и на тот случай, если кто-то был любопытен или имел какие-либо комментарии. Пожалуйста, простите жесткое форматирование; Это должно было избавиться от горизонтальной прокрутки.
Дайте мне знать в разделе комментариев, если вы используете это. Мне было бы интересно услышать, было ли это полезно кому-либо еще.
Нам понадобятся следующие заголовки:
#include <boost/range/iterator_range.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <vector>
Помощник для привязки к существующему refcounted object
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 ){}
};