基于自定义容器范围的迭代
Custom container range-based iteration
我有一个自定义容器,我想在基于范围的for循环中使用它。容器在某种程度上是基于向量的,比如:
template<typename T>
class IDMap
{
private:
struct Item {
uint16_t mVersion;
T mItem;
template <typename... Arguments>
Item(uint16_t version, Arguments&&... args) : mVersion(version), mItem(args...)
{
}
};
public:
typedef uint32_t ItemID;
template <typename... Arguments>
ItemID AddItem(Arguments&&... args);
void MarkAsFree(const ItemID id);
T& GetItem(const ItemID id);
T* TryGetItem(const ItemID id);
void Clear();
private:
std::vector<Item> mItems;
std::vector<uint16_t> mFreeIndices;
};
我想迭代mItems
向量,但只返回mItem
成员,而不是整个Item
结构。有什么简单/优雅的方法可以做到这一点吗?
您必须提供begin
和end
函数,这两个函数都返回相应的迭代器,迭代器本身实现运算符++
、!=
和*
。begin
和end
功能可以是独立的或作为成员。
首先实现一个迭代器,它具有您想要的行为。您可以将其实现为std::vector::iterator
的包装器,以节省大部分"核心"工作。
以下是未经测试的代码
基本上,在类IDMap中,添加:
class ItemIterator {
// based on vector iterator
std::vector<Item>::iterator i;
public:
ItemIterator(std::vector<Item>::iterator i) : i(i) {}
// incrementing
ItemIterator & operator ++() { ++i; return *this; }
ItemIterator operator ++(int) { const_iterator old(*this); ++(*this); return old; }
// comparison
bool operator!=(const ItemIterator &o) const { return i != o.i; }
// dereferencing
const T & operator*() const { return i->mItem; }
};
using iterator = ItemIterator;
using value_type = T;
ItemIterator begin() const { return ItemIterator(mItems.begin()); }
ItemIterator end() const { return ItemIterator(mItems.end() ); }
如果您希望在IDMap上支持多种类型的"特殊迭代",例如在索引上或在"整个"Item
上,则应该将上面的所有内容都封装在另一个适配器中。然后可以使用成员方法访问该适配器,如.items()
。
简要示例:
class IDMap {
// (your code)
public:
struct ItemsAdaptor {
// (insert above iterator definition + usings)
ItemsAdaptor(std::vector<Item>::iterator b,
std::vector<Item>::iterator e)
: b{b}, e{e}
{}
ItemIterator begin() const { return b; }
ItemIterator end() const { return e; }
private:
ItemIterator b, e;
};
ItemsAdaptor items() const {
return ItemsAdaptor(mItems.begin(), mItems.end());
}
};
然后,你可以写:
IDMap<int> map = ...;
for (int i : map.items()) {
...
}
如果您希望基于的范围适用于您的容器,您必须提供返回前向迭代器的begin和end函数。
typedef std::vector<Item>::iterator iterator;
typedef std::vector<Item>::const_iterator const_iterator;
iterator begin()
{
return mItems.begin();
}
const_iterator begin() const;
{
return mItems.begin();
}
//also add end functions, and viola.
这将返回整个项结构。如果必须只返回mItem,则必须编写自己的迭代器适配器,并使用它来代替vector。
相关文章:
- 基于范围的 for 循环:迭代使用一个元素扩展的向量
- 使用基于范围的循环迭代矢量时出现问题
- 转到基于范围的 for 循环中的下一个迭代器
- C++:返回一个基于范围 for 循环迭代器,其中包含继承对象
- 迭代器范围的平衡分区,没有LegacyRandomAccessIterator
- 迭代嵌套映射与范围为循环:没有名为"first"的成员
- 为什么范围算法与 std 的迭代器不兼容?
- Deque 迭代器超出范围
- unordered_set范围插入与迭代器
- 类型不可知的抽象以使用相同的运行时接口处理正向和反向迭代器和范围?
- 如何使用基于范围的for循环迭代Rapidjson文档(它本身就是一个JSON数组)
- 如何在具有可变端点的基于范围的for循环中迭代
- 访问基于范围的循环(如for_each)中的std::map迭代器
- 迭代器的范围 TS 和 C++20 概念是否需要能够使用"运算符>"?
- 列出超出范围的擦除迭代器
- 基于 C++ 范围的 std::vector 迭代的顺序
- 如何使用提升范围将自定义迭代器封装在函数中
- 无法取消引用超出范围的向量迭代器 - 有什么问题?
- C++:指向错误元素的提升范围迭代器
- re C++范围迭代器:只有一个类不好吗