假设我有一个虚拟基类 Base
,它在某种程度上表现得像一个容器,有两个派生类 VectorLike
和 RangeLike
.
我想实现如下目标:
class VectorLike : public Base {
std::vector<int> data;
public:
virtual std::vector<int>::const_iterator cbegin() { return data.cbegin() }
virtual std::vector<int>::const_iterator cend() { return data.cend() }
}
class RangeLike : public Base {
int min, max;
class const_iterator {
int x;
public:
int operator++() { return ++x }
bool operator==( const_iterator rhs ) { return x == rhs.x }
const_iterator( int y ) { x = y }
}
public:
virtual const_iterator cbegin() { return const_iterator( min ); }
virtual const_iterator cend() { return const_iterator( max ); }
}
此代码无法编译,因为 std::vector<int>::const_iterator
和 RangeLike::const_iterator
不相同或covariant .
要实现第二个目标,我需要一个迭代器基类,std::vector<int>::const_iterator
都来自该基类。和 RangeLike::const_iterator
会得出。但后来还是cbegin()
和 cend()
将不得不返回指向迭代器的指针,这将造成更大的困惑。
我的问题是,是否有可能实现类似上述代码的东西,如果可以的话如何实现?
最佳答案
这是一个多态 const int 迭代器的实现。您可以使用任何迭代器类型(包括指针)构造它,其中 std::iterator_traits<Iter>::value_type
解析为 int
.
std::vector<int>
都应该是这种情况和 your_range_type<int>
.
这应该可以帮助您入门。
#include <iostream>
#include <vector>
#include <array>
#include <memory>
#include <algorithm>
struct poly_const_iterator
{
using value_type = int;
struct concept {
virtual void next(int n) = 0;
virtual const value_type& deref() const = 0;
virtual bool equal(const void* other) const = 0;
virtual std::unique_ptr<concept> clone() const = 0;
virtual const std::type_info& type() const = 0;
virtual const void* address() const = 0;
virtual ~concept() = default;
};
template<class Iter>
struct model : concept
{
model(Iter iter) : _iter(iter) {}
void next(int n) override { _iter = std::next(_iter, n); }
const value_type& deref() const override { return *_iter; }
bool equal(const void* rp) const override { return _iter == static_cast<const model*>(rp)->_iter; }
std::unique_ptr<concept> clone() const override { return std::make_unique<model>(*this); }
const std::type_info& type() const override { return typeid(_iter); }
const void* address() const override { return this; }
Iter _iter;
};
std::unique_ptr<concept> _impl;
public:
// interface
// todo: constrain Iter to be something that iterates value_type
template<class Iter>
poly_const_iterator(Iter iter) : _impl(std::make_unique<model<Iter>>(iter)) {};
poly_const_iterator(const poly_const_iterator& r) : _impl(r._impl->clone()) {};
const value_type& operator*() const {
return _impl->deref();
}
poly_const_iterator& operator++() {
_impl->next(1);
return *this;
}
bool operator==(const poly_const_iterator& r) const {
return _impl->type() == r._impl->type()
and _impl->equal(r._impl->address());
}
bool operator != (const poly_const_iterator& r) const {
return not(*this == r);
}
};
void emit(poly_const_iterator from, poly_const_iterator to)
{
std::copy(from, to, std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
}
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
std::array<int, 5> a = { 6, 7,8, 9, 0 };
emit(std::begin(v), std::end(v));
emit(std::begin(a), std::end(a));
return 0;
}
预期结果:
1, 2, 3, 4, 5,
6, 7, 8, 9, 0,
关于c++ - 使用虚拟派生方法返回不同的迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35866041/