101*_*010 5 c++ iterator stl legacy-code void-pointers
在过去(当C是幕后的主流语言和STL /模板是Alex Stepanov的梦想)时,为了使程序员实现函数和数据容器的通用性,将void*其用作输入参数(用于函数通用性)或底层容器类型(对于数据容器的一般性).一个典型的例子是qsort,它位于<cstdlib>.
现在,在处理遗留的代码库或恐龙编写的代码时,您很可能会偶然发现在这种范例下设计的数据结构,这些数据结构将其元素保留在void**缓冲区中.您的主要目标之一应该是逐步将代码库移至使用现代STL容器和算法,直到这些旧数据结构过时.然而,也有恐龙要与之抗争,也许是一个恰好是你的经理的霸王龙.为了使他们相信C++/STL的优越性而不质疑遗留数据结构的"可用性",这些遗留数据结构已经运行了多年而没有问题并且没有冒犯他们(因为他们可能是原作者),我决定参与政治问题.
我以为是制作一个模板迭代器,可以处理这样的void**缓冲区,并会作为与STL算法(如桥std::sort,std::copy等等).
下面是一个非常早期的迭代器:
template<typename T>
class Iterator : public std::iterator<std::bidirectional_iterator_tag, T> {
using T_ptr = std::remove_pointer_t<T>*;
void **pos;
public:
Iterator(void **pos_) : pos(pos_) { }
bool operator==(Iterator const &other) const { return pos == other.pos; }
bool operator!=(Iterator const &other) const { return pos != other.pos; }
bool operator<( Iterator const &other) const { return pos < other.pos; }
bool operator>( Iterator const &other) const { return pos > other.pos; }
bool operator<=(Iterator const &other) const { return pos <= other.pos; }
bool operator>=(Iterator const &other) const { return pos >= other.pos; }
Iterator& operator++() {
++pos;
return *this;
}
Iterator operator++(int) {
Iterator out(*this);
++pos;
return out;
}
Iterator& operator--() {
--pos;
return *this;
}
Iterator operator--(int) {
Iterator out(*this);
--pos;
return out;
}
Iterator& operator+=(int const n) {
pos += n;
return *this;
}
Iterator& operator-=(int const n) {
pos -= n;
return *this;
}
T& operator[](int const n) { *static_cast<T_ptr>(*(pos + n)); }
T& operator*() { return *static_cast<T_ptr>(*pos); }
T_ptr operator->() { return static_cast<T_ptr>(*pos); }
friend Iterator operator+(Iterator const &lhs, int const n) {
Iterator out(lhs);
out.pos += n;
return out;
}
friend Iterator operator-(Iterator const &lhs, int const n) {
Iterator out(lhs);
out.pos -= n;
return out;
}
friend Iterator operator+(int const n, Iterator const &rhs) {
Iterator out(rhs);
out.pos += n;
return out;
}
friend Iterator& operator-(int const n, Iterator const &rhs) {
Iterator out(rhs);
out.pos -= n;
return out;
}
friend int operator-(Iterator const &A, Iterator const &B) { return B.pos - A.pos; }
};
Run Code Online (Sandbox Code Playgroud)
我的目标是以下列方式使用此迭代器.假设我有以下课程:
struct Foo {
int val = 0;
explicit Foo(int val_) : val(val_) {}
Foo() = default;
Foo(Foo const&) = default;
Foo(Foo &&) = default;
Foo& operator=(Foo const&) = default;
Foo& operator=(Foo &&) = default;
bool operator< (Foo const& rhs) const { return val < rhs.val; }
bool operator==(Foo const& rhs) const { return val == rhs.val; }
};
Run Code Online (Sandbox Code Playgroud)
以下缓冲区void*:
Foo f1(1), f2(2), f3(3), f4(4);
void* v[] = {&f4, &f2, &f1, &f3};
Run Code Online (Sandbox Code Playgroud)
我想使用它相对于它包含的对象std::sort进行v定向排序Foo:
std::sort(Iterator<Foo>(v), Iterator<Foo>(v + sizeof(v) / sizeof(void*)));
Run Code Online (Sandbox Code Playgroud)
我一直小心翼翼地继承我的迭代器,而不是为了避免将缓冲区视为与可能具有的任何含义相关联的s.std::iterator<std::bidirectional_iterator_tag, T>std::iterator<std::random_access_iterator_tag, T>void**bufferT
这个迭代器方案安全吗?我必须注意到有什么怪癖或奇怪之处吗?