问题描述
我创建了一个动态容器,用于将字节存储为 uint8_t
并在容器类中实现了一个迭代器类。迭代器按预期遍历字节。但是这些字节是用头格式化的,所以我想实现另一个迭代器来跳过基于字节头的字节数组。是否可以根据首先声明的类与 for(auto &x: container)
一起使用时运行两个迭代器类?还是有其他方法可以做到这一点?
当前迭代器和容器
class container {
public:
container() : s(0),c(2),data(new uint8_t[2]) {};
container(size_t reserve) : s(0),c(reserve + 1),data(new uint8_t[reserve + 1]) {};
~container();
// container insert,operators etc...
// iterator class
class Iterator {
public:
uint8_t* ptr;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = uint8_t;
using pointer = uint8_t*;
using reference = uint8_t&;
Iterator(pointer m_ptr) : ptr(m_ptr) { std::cout << "In iterator 1" << std::endl; }
reference operator*() const;
pointer operator->();
Iterator& operator++();
Iterator operator++(int);
Iterator& operator+=(int const& lhs);
Iterator operator+(int const& lhs);
friend bool operator== (const Iterator& a,const Iterator& b);
friend bool operator!= (const Iterator& a,const Iterator& b);
};
Iterator begin() const;
Iterator end() const;
private:
uint8_t* data;
size_t s;
size_t c;
};
解决方法
不,范围迭代语法是这样的:调用容器的begin()
和end()
的代理;然后迭代返回的序列。这是唯一有效的方法。
C++20 添加了 range 库,可用于将两个单独的迭代器序列组合在一起。在 C++20 之前,这种情况下最常见的选择是声明第三个迭代器类,它代理两个底层迭代器类的组合序列,然后将此代理迭代器类与 begin()
和 { {1}}。基本方法相当简单:
-
end()
返回用两个底层迭代器类的开始和结束迭代器值初始化的第三个迭代器类,begin()
返回用两个底层迭代器类的结束迭代器值初始化的第三个迭代器类用于代理的内部开始和结束迭代器值的迭代器类(即,对于它们两者的 begin=end)。 -
end()
和/或*
运算符重载检查第一个迭代器类的代理起始迭代器值是否已经达到其结束值。如果不是,则使用它来实现->
和*
,否则使用第二个代理开始迭代器值。 -
各种前向/增量重载使第一个迭代器类的代理起始迭代器值前进。如果它已经在它的迭代器类的结束迭代器值上,那么第二个迭代器类的代理开始迭代器值会提前。
您不能根据声明顺序使迭代行为不同。这甚至意味着什么?不知何故,这就像要求同一个类根据上下文或随机地表现出不同的行为。
然而,你可以做的是实现这样的代码:
for (auto x: my_container.raw()) { ... }
for (auto x: my_container.rows()) { ... }
for (auto x: my_container.columns()) { ... }
for (auto x: my_container.pixels()) { ... }
注意:我只是猜测您提到的标头是位图标头,并且您正在处理图像文件。
顺便说一句:你的代码有很多问题,虽然不是灾难性的,但仍然是改进的好机会,例如使用原始 new[]
内存分配,应该是 std::vector
代替。考虑将您的工作(!)代码发布在
codereview.stackexchange.com。