如何使用 private std::vector base class 编写正向迭代器
how to write forward iterator using private std::vector base class
我需要一个向量 class 来公开 std::vector API 的一小部分。一切正常,除了基于范围的。在这里,我尝试实现一个前向迭代器,但它无法编译。
#include <vector>
#include <iostream>
template <class T>
class OwningVector : private std::vector<T*> {
using super = std::vector<T*>;
public:
OwningVector() = default;
~OwningVector()
{
for (T* e : *this)
delete e;
super::clear();
}
OwningVector(const OwningVector& other)
: super()
{
super::reserve(other.size());
for (T* e : other)
super::emplace_back(e->clone());
}
OwningVector& operator=(const OwningVector& other)
{
if (this == &other)
return *this;
OwningVector ret(other);
swap(*this, ret);
return *this;
}
void emplace_back(T* e) { super::emplace_back(e); }
size_t size() const { return super::size(); }
T* const& operator[](int i) const { return super::operator[](i); }
T* const& at(int i) const { return super::at(i); }
const T* back() const { return super::back(); }
// Here the questionable part of my code:
class Iterator : public std::vector<T*>::iterator {};
Iterator begin() const { return super::begin(); }
Iterator end() const { return super::end(); }
Iterator begin() { return super::begin(); }
Iterator end() { return super::end(); }
};
class A {
public:
A(int m) : m(m) {}
int m;
};
int main() {
OwningVector<A> v;
v.emplace_back(new A(1));
for (const A*const a: v)
std::cout << a->m << std::endl;
}
编译失败:
h.cpp: In instantiation of ‘OwningVector<T>::Iterator OwningVector<T>::begin() [with T = A]’:
h.cpp:56:27: required from here
h.cpp:43:43: error: could not convert ‘((OwningVector<A>*)this)->OwningVector<A>::<anonymous>.std::vector<A*, std::allocator<A*> >::begin()’ from ‘std::vector<A*, std::allocator<A*> >::iterator’ to ‘OwningVector<A>::Iterator’
43 | Iterator begin() { return super::begin(); }
| ~~~~~~~~~~~~^~
| |
| std::vector<A*, std::allocator<A*> >::iterator
h.cpp: In instantiation of ‘OwningVector<T>::Iterator OwningVector<T>::end() [with T = A]’:
h.cpp:56:27: required from here
h.cpp:44:39: error: could not convert ‘((OwningVector<A>*)this)->OwningVector<A>::<anonymous>.std::vector<A*, std::allocator<A*> >::end()’ from ‘std::vector<A*, std::allocator<A*> >::iterator’ to ‘OwningVector<A>::Iterator’
44 | Iterator end() { return super::end(); }
| ~~~~~~~~~~^~
| |
| std::vector<A*, std::allocator<A*> >::iterator
class Iterator : public std::vector<T*>::iterator {};
为什么?这看起来像是某种其他语言的实现方式。它也不能保证工作,因为 vector<T*>::iterator
实际上可能是一个指针类型,在这种情况下你不能从它派生。
using Iterator = typename super::iterator;
using ConstIterator = typename super::const_iterator;
ConstIterator begin() const { return super::begin(); }
ConstIterator end() const { return super::end(); }
Iterator begin() { return super::begin(); }
Iterator end() { return super::end(); }
这行得通。 typename
在 C++17 之前是必需的,对于 C++20 可以删除。
我需要一个向量 class 来公开 std::vector API 的一小部分。一切正常,除了基于范围的。在这里,我尝试实现一个前向迭代器,但它无法编译。
#include <vector>
#include <iostream>
template <class T>
class OwningVector : private std::vector<T*> {
using super = std::vector<T*>;
public:
OwningVector() = default;
~OwningVector()
{
for (T* e : *this)
delete e;
super::clear();
}
OwningVector(const OwningVector& other)
: super()
{
super::reserve(other.size());
for (T* e : other)
super::emplace_back(e->clone());
}
OwningVector& operator=(const OwningVector& other)
{
if (this == &other)
return *this;
OwningVector ret(other);
swap(*this, ret);
return *this;
}
void emplace_back(T* e) { super::emplace_back(e); }
size_t size() const { return super::size(); }
T* const& operator[](int i) const { return super::operator[](i); }
T* const& at(int i) const { return super::at(i); }
const T* back() const { return super::back(); }
// Here the questionable part of my code:
class Iterator : public std::vector<T*>::iterator {};
Iterator begin() const { return super::begin(); }
Iterator end() const { return super::end(); }
Iterator begin() { return super::begin(); }
Iterator end() { return super::end(); }
};
class A {
public:
A(int m) : m(m) {}
int m;
};
int main() {
OwningVector<A> v;
v.emplace_back(new A(1));
for (const A*const a: v)
std::cout << a->m << std::endl;
}
编译失败:
h.cpp: In instantiation of ‘OwningVector<T>::Iterator OwningVector<T>::begin() [with T = A]’:
h.cpp:56:27: required from here
h.cpp:43:43: error: could not convert ‘((OwningVector<A>*)this)->OwningVector<A>::<anonymous>.std::vector<A*, std::allocator<A*> >::begin()’ from ‘std::vector<A*, std::allocator<A*> >::iterator’ to ‘OwningVector<A>::Iterator’
43 | Iterator begin() { return super::begin(); }
| ~~~~~~~~~~~~^~
| |
| std::vector<A*, std::allocator<A*> >::iterator
h.cpp: In instantiation of ‘OwningVector<T>::Iterator OwningVector<T>::end() [with T = A]’:
h.cpp:56:27: required from here
h.cpp:44:39: error: could not convert ‘((OwningVector<A>*)this)->OwningVector<A>::<anonymous>.std::vector<A*, std::allocator<A*> >::end()’ from ‘std::vector<A*, std::allocator<A*> >::iterator’ to ‘OwningVector<A>::Iterator’
44 | Iterator end() { return super::end(); }
| ~~~~~~~~~~^~
| |
| std::vector<A*, std::allocator<A*> >::iterator
class Iterator : public std::vector<T*>::iterator {};
为什么?这看起来像是某种其他语言的实现方式。它也不能保证工作,因为 vector<T*>::iterator
实际上可能是一个指针类型,在这种情况下你不能从它派生。
using Iterator = typename super::iterator;
using ConstIterator = typename super::const_iterator;
ConstIterator begin() const { return super::begin(); }
ConstIterator end() const { return super::end(); }
Iterator begin() { return super::begin(); }
Iterator end() { return super::end(); }
这行得通。 typename
在 C++17 之前是必需的,对于 C++20 可以删除。