是否有随机访问容器类型接受预填充&am​​p;预分配缓冲区?

时间:2011-07-28 03:36:35

标签: c++ boost stl iterator containers

我自己要写点东西,因为我没找到我要找的东西,但我想在潜入之前先问问群众。

  • 是否存在允许传入预填充缓冲区的boost或stl随机访问容器类型?

虚构(?)容器类型将运行如下:

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

  SpecialVector<int> mySpecialIntVector( blob, blobSize );

基本上我将旧库与c样式的原始指针连接到缓冲区,但是想要使用C ++样式容器语义而不需要复制步骤。我希望有的是std :: vector plus preallocated&amp;预填充缓冲区构造函数和减去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;

有人知道有关这些限制的提升或stl模板吗?

3 个答案:

答案 0 :(得分:8)

根据Dennis 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;
  }

谢谢丹尼斯! :)

答案 1 :(得分:4)

没有你想要的东西,这只是语言的缺点。如果您对分配器静态地猜测一个良好的预期最大元素数量感到满意,那么您可以在分配器中嵌入一个普通的C数组并尽可能地推迟它;这通常称为自动缓冲区。


旧答案:

所有标准库容器都允许您指定分配器。你可以创建一个缓冲区分配器。

答案 2 :(得分:0)

我想我会发布我最后用于后代的自定义解决方案,以防万一有人好奇或有任何意见。请原谅严格的格式;这是为了摆脱水平滚动。

如果您使用此功能,请在评论部分告诉我。我很想知道它是否对其他人有用。

我们需要以下标题:

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

挂钩到现有refcounted对象的助手

 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 ){}

};