假设我有一个虚拟基类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()
必须返回指向迭代器的指针,这将造成更大的混乱。
我的问题是,是否有可能实现类似上述代码的内容,如果是这样的话?
答案 0 :(得分:4)
这是一个多态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,