The C++ STL does not seem to use purely abstract base classes (aka interfaces) very often. I know that most things can be achieved with the STL algorithms or clever template metaprogramming.
But still, for some use cases (for example, in an API, if I do not want to be specific about the type of container I get, just about the elements it contains), an interface of the following form would be nice:
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;
};
If the STL containers implement this class as non-virtual function, this would, in my opinion, not affect performance (if I use the containers directly and not via this interface). So why are there so few "interfaces" in the STL? Or am I just thinking too much in "Java" terms?
Stack does not have iterators, by definition of stack. If you need stack with iterators, you'll need to implement it yourself on top of other container (std::list, std::vector, etc).
Iterators are one of the four pillars of the Standard Template Library or STL in C++. An iterator is used to point to the memory address of the STL container classes.
Iterators are used to point at the memory addresses of STL containers. They are primarily used in sequences of numbers, characters etc. They reduce the complexity and execution time of the program.
Iterators are used to traverse from one element to another element, a process is known as iterating through the container. The main advantage of an iterator is to provide a common interface for all the containers type. Iterators make the algorithm independent of the type of the container used.
STL (which is a subset of the standard library) does not use OOP (as in runtime polymorphism) at all and that's by design.
With your design, wouldn't there be problems returning iterators by value (covariance doesn't work for value types)? That is, wouldn't inevitably the whole thing either have to rely on static members (that you can return by reference) or on heap-allocated iterators? The latter would seem rather awkward in a non-garbage-collected language.
What you are describing (an iterator templated on value type) can be achieved using a technique called type-erasure (and you can find any_iterator
implementations out there) just like boost's function
and any
types.
The basic idea is:
//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();
//...
}
It may be more complicated than that (e.g need to do something about describing and enforcing iterator category?, how would comparing two any_iterators work (double dispatch/RTTI?)).
The reason you don't see a lot of "interface"-style abstract base classes in the STL is because it relies so heavily on C++ templates. When you use C++ templates, pretty much any class whatsoever, no matter what its parentage may be, will do as long as it supports all the methods the template tries to use.
There is sort of an implied interface, but actually writing it out is unnessecary. In my own coding I tend to write one anyway, just as a convenience to the user, but that isn't how the STL writers roll.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With