c++ - 如何从 unique_ptr<Base> 的 vector 中获取派生迭代器?

标签 c++ c++11 vector iterator unique-ptr

我有一个基类 ( Container ),它在 Base 的 vector 中包含各种对象 ( std::unique_ptr<Base> 项)我有一个派生类 ( FolderOfFolders ),它只包含特定项目 ( Folder 项目)。我想使用 range-based-for 遍历该特定对象( FolderOfFolder ),但我不知道该怎么做。使用 range-based-for 我可以返回 std::unique_ptr<Base>项目,但我想要 const Folder*那些。我知道我需要一个 begin(), end() 对来为基于范围的 for 提供迭代器,但我需要一个来自 std::unique_ptr<Base> 的转换至 const Folder* .这有可能吗?

class Container : public Base {
  public:
    // I want to get back these as Folder* from FolderOfFolders
    std::vector<std::unique_ptr<Base>> items;
};

class Folder : public Container {
  public:
   // I want to call this when I traverse FolderOfFolders with range-based-for
   void folderMethod();
   ...
};

class SystemFolder : public Folder {
  public:
   ...
};

class UserFolder : public Folder {
  public:
   ...
};

class FolderOfFolders : public Folder {
  public:

    // I know that every item is a Folder in items
    // can I get an iterator to a Folder* ?!
    iterator begin() {
      //  ???
      return items.begin();
    }
    iterator end() {
       // ???
       return items.end();
    }
};

我想用它作为

FolderOfFolders folderOfFolders;
for (folder : folderOfFolders)
  folder->folderMethod();

最佳答案

#include <boost/iterator/transform_iterator.hpp>

struct Downcast
{
  typedef const Folder* result_type;

  result_type operator()(const std::unique_ptr<Base>& p) const
  { return static_cast<const Folder*>(p.get()); }
};

class FolderOfFolders : public Folder {
  public:

    typedef boost::transform_iterator<Downcast, decltype(items)::iterator> iterator;

    iterator begin() {
      return iterator(items.begin(), Downcast());
    }
    iterator end() {
      return iterator(items.end(), Downcast());
    }
};

注意因为 FolderOfFolders::iterator::operator* 按值返回一个 const Folder*,这意味着 FolderOfFolders::iterator::reference 不是一个引用类型,因此迭代器只是一个 InputIterator,而不是像底层 vector::iterator 那样的 RandomAccessIterator,但这足以与基于范围的 for 一起使用。

然而,这种“一切都是Base,所有集合都是Base的集合”的说法有点像Java。有更好的设计。即使您必须存储 Base 的容器,您也可以这样做而不必更改迭代器类型:

const Folder& asFolder(const Base& b) {
  return dynamic_cast<const Folder&>(b); 
}

class FolderOfFolders : public Folder {
  public:

    typedef decltype(items)::iterator iterator;

    iterator begin() {
      return items.begin();
    }
    iterator end() {
      return items.end();
    }
};

...

for (auto& base_ptr : folderOfFolders)
  asFolder(*base_ptr).folderMethod();

关于c++ - 如何从 unique_ptr<Base> 的 vector 中获取派生迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22696806/

相关文章:

c++ - MSXML get_documentElement() & 返回指向 COM 接口(interface)的指针

c++ - 我还需要对 algorithm::join 使用 boost 吗?

c++ - 创建一个返回 std::mem_fn 或 boost::mem_fn 的通用包装器

c++ - 在 copy-and-swap 习语中实现交换

double 类型的 C++ 变量总是将它们的值更改为 -9,25596e+061

c++ - 我有一大堆边界框,如何计算重复项?

c++ - iostream 到 zlib 和 C++ 文件?

c++ - 为什么 128 位变量应该与 16 字节边界对齐

c++ - 如何在队列中存储位于 vector 中的对象的unique_ptr

c++ - 如何连接/合并 vector