sum*_*ier 10 abstract-class iterator design-patterns stl
C++ STL似乎不经常使用纯粹的抽象基类(也就是接口).我知道大多数事情都可以通过STL算法或聪明的模板元编程来实现.
但是,对于某些用例(例如,在API中,如果我不想具体说明我得到的容器类型,只是它包含的元素),以下形式的接口会很好:
template<typename T> struct forward_iterable {
struct iterator {
typedef T value_type;
typedef T& reference;
typedef T* pointer;
virtual reference operator*() const = 0;
virtual pointer operator->() const = 0;
virtual bool operator==(const iterator&) const = 0;
virtual bool operator!=(const iterator&) const = 0;
virtual operator const_iterator() const = 0;
virtual iterator& operator++() = 0;
virtual iterator operator++(int) = 0;
};
struct const_iterator { ... }; // similar, but with const references
virtual iterator begin() = 0;
virtual const_iterator begin() const = 0;
virtual iterator end() = 0;
virtual const_iterator end() const = 0;
};
Run Code Online (Sandbox Code Playgroud)
如果STL容器将此类实现为非虚函数,我认为这不会影响性能(如果我直接使用容器而不是通过此接口).那么为什么STL中的"接口"如此之少呢?或者我只是在用"Java"术语思考太多?
STL(它是标准库的一个子集)根本不使用OOP(如在运行时多态性中),这是设计的.
根据您的设计,按值返回迭代器是否存在问题(协方差对值类型不起作用)?也就是说,整个事件不可避免地要依赖静态成员(可以通过引用返回)还是依赖于堆分配的迭代器?后者在非垃圾收集语言中看起来相当尴尬.
您正在描述的内容(在值类型上模板化的迭代器)可以使用称为类型擦除的技术(您可以any_iterator在那里找到实现)来实现,就像boost function和any类型一样.
基本思路是:
//less templated interface
template <class T>
class any_iterator_base
{
virtual void increment() = 0;
/*...*/
};
//derived class templated on iterator type
template <class Iter, class T>
class any_iterator_impl: public any_iterator_base<T>
{
Iter it;
virtual void increment() { ++it; }
/*...*/
};
//and a class for the user which makes it all act like a regular value type
template <class T>
class any_iterator
{
shared_ptr<any_iterator_base<T> > it;
public:
template <class Iter>
any_iterator(Iter iterator): it(new any_iterator_impl<Iter, T>(iterator)) {}
any_iterator& operator++() { it->increment(); return *this; }
//...
};
int main()
{
std::vector<int> vec;
any_iterator<int> it = vec.begin();
//...
}
Run Code Online (Sandbox Code Playgroud)
它可能比那更复杂(例如,需要做一些关于描述和实施迭代器类别的东西?,如何比较两个any_iterator工作(double dispatch/RTTI?)).