我有一个基类(Container
),它在Base
的向量中包含各种对象(std::unique_ptr<Base>
项),并且我有一个派生类(FolderOfFolders
)只保存特定项目(Folder
项目)。我想使用基于范围的for来遍历该特定对象(FolderOfFolder
),但我不知道该怎么做。使用基于范围的 - 我可以返回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();
答案 0 :(得分:3)
#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());
}
};
N.B。因为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();
答案 1 :(得分:0)
您的解决方案是参考:
for (auto &folder : folderOfFolders)
folder->folderMehod();
std::unique_ptr<>
个对象不是可复制的,但您可以使用引用绑定迭代。