CRTP 容器

san*_*san 5 c++ templates crtp

我正在尝试一些模板编程,对此我很陌生。我想要实现的是一些包含 STL 容器的 CRTP 类。让class A{};我们以(编译时)基类为例,class B{};class C{};是在编译时按照 CRTP 样式“派生”的。

现在 和BC将包含容器。为了示例的目的,将其分别设为 astd::vector和 a std::set。现在,我想通过 abegin()和一个end()公开前向迭代器的函数来公开这些迭代器。但是,我不想公开内部的确切容器是什么B,并且C我想为 定义这些函数A,以便在调用时使用正确的B容器C

这可能吗 ?现在我的计划是有一个Iterator内部类BC它将包含实际的迭代器(视情况而定的向量或集合)并将调用委托给它。然而,这似乎是很多重复的粘合代码,我怀疑有更好的选择。

我有一些问题:

  1. 我如何声明 、 中的内部类AB以便C它与 CRTP 配合良好。我需要为A,B和复制它吗C?它可以是一个空类吗A?我可以用专门的实现来掩盖它们BC

  2. 如何以更少的胶水和更少的重复来公开迭代器?

我不想与 boost 这样的外部库创建依赖关系,并且只想坚持使用 std。所以我必须自己实现我需要的任何额外内容。感谢您的所有帮助。

lap*_*apk 1

如果我理解正确的话,你正在寻找这样的东西。请注意,我制作了一些简单的构造函数只是为了说明它的工作原理。还有,你的class A就是我的class TWrapperBaseB- TWrapperBC- TWrapperC。另一件事,对于这个特定的示例,您实际上并不需要有两个派生类,但我假设您的类BC明显不同,以证明它在您的程序中是合理的。

编辑:忘记在循环中增加 lIterSet 。

#include <vector>
#include <set>
#include <iostream>

template< typename PType, typename PContainer >
class TWrapperBase
{
 public:
  typedef PType TType;
  typedef PContainer TContainer;
  typedef typename TContainer::iterator TIterator;
 protected:
  TContainer mContainer;
 public:
  TWrapperBase( const TContainer& pOriginal ) :
   mContainer( pOriginal )
  {
  }
  TIterator begin( void )
  {
   return mContainer.begin();
  }
  TIterator end( void )
  {
   return mContainer.end();
  }
};

template< typename PType, class PContainer = std::vector< PType > >
class TWrapperB : public TWrapperBase< PType, PContainer >
{
 public:
  TWrapperB( const TContainer& pOriginal ) :
   TWrapperBase( pOriginal )
  {
  }
};

template< typename PType, class PContainer = std::set< PType > >
class TWrapperC : public TWrapperBase< PType, PContainer >
{
 public:
  TWrapperC( const TContainer& pOriginal ) :
   TWrapperBase( pOriginal )
  {
  }
};

int main( void )
{
 int lInit[] =
 {
 1, 2, 3
 };

 std::vector< int > lVec( lInit, lInit + 3 );
 std::set< int > lSet( lInit, lInit + 3 );

 TWrapperB< int > lB( lVec );
 TWrapperC< int > lC( lSet );

 std::vector< int >::iterator lIterVec = lB.begin();
 std::set< int >::iterator lIterSet = lC.begin();

 while( lIterVec < lB.end() )
 {
  std::cout << "vector: " << *lIterVec << " / set: " << *lIterSet << std::endl;
  lIterVec++;    
  lIterSet++;
 }

 return 0;
}
Run Code Online (Sandbox Code Playgroud)