Is there a random access container type that accepts a prefilled & preallocated buffer?
I'm about to write something myself since I didn't find what I was looking for, but figured I should ask the crowd before diving in.
- Is there a boost or stl random access container type that allows passing in of prefilled buffer?
The imaginary(?) container type would operate something like this:
const int blobSize = unpackBlobSize( msg );
int * blob = unpackBlobData( msg );
SpecialVector<int> mySpecialIntVector( blob, blobSize );
Basically I'm interfacing an old library with c-style raw pointers-to-buffers, but would like to use C++ style container semantics without requiring a copy step. What I would hope to have is std::vector plus preallocated & prefilled buffer constructor and, minus resize.
Libeigen has this sort of functionality with their Eigen::Map which allows things like the following:
int array[9];
for(int i = 0; i < 9; ++i)
array[i] = i;
stl::cout << Eigen::Map<Eigen::Matrix3i>(array) 开发者_如何转开发<< stl::endl;
Anyone know of a boost or stl template that covers these constraints?
Going from Dennis Zickenfoose's comment, I looked up Boost.range seems to offer the perfect solution:
#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;
}
Thanks Dennis! : )
There's nothing like you want, this is just a shortcoming of the language. If you were satisfied with having the allocator statically guess a good expected maximum element count, you could just embed a normal C array inside an allocator and defer to it as long as possible; this is usually called an auto buffer.
Old Answer:
All of the standard library containers allow you to specify an allocator. You can make a buffer allocator.
I figured I'd post the custom solution I ended up using for posterity and in case anyone was curious or had any comments. Please forgive the tight formatting; It was to get rid of the horizontal scroll.
Do let me know in the comment section if you use this. I'd be curious to hear if it was useful to anyone else.
We'll need the following headers:
#include <boost/range/iterator_range.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <vector>
A helper to hook onto an existing 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;
};
And then:
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 ){}
};
精彩评论