ポリモーフィック イテレータ? 身震い
使用例:
#include <iostream>
struct Animal
{
virtual void print() = 0;
};
struct Elephant : Animal
{
virtual void print() override { std::cout << "toot"; }
};
struct Cat : Animal
{
virtual void print() override { std::cout << "meow"; }
};
struct Fox : Animal
{
virtual void print() override
{ std::cout << "ring-ding-ding-ding-dingeringeding"; }
};
#include <vector>
template<class T>
using simple_vector = std::vector<T>;
int main()
{
std::vector<Elephant> elephants(5);
std::vector<Cat> cats(3);
std::vector<Fox> foxes(1);
polymorphic_range_container<simple_vector, Animal> animals;
animals.push_back( std::make_pair(elephants.begin(), elephants.end()) );
animals.push_back( std::make_pair(cats.begin(), cats.end()) );
animals.push_back( std::make_pair(foxes.begin(), foxes.end()) );
for(auto& animal : animals)
{
animal.print(); std::cout << ", ";
}
std::cout << std::endl;
}
実装 (基本):
#include <memory>
#include <algorithm>
#include <iterator>
#include <utility>
template<class T>
struct iterator_base
{
virtual void advance(int i) = 0;
virtual T& get() const = 0;
virtual bool equal(iterator_base const&) const = 0;
};
template<class ValueType, class Container, class Id>
struct polymorphic_iterator
{
polymorphic_iterator& operator++()
{
impl->advance(1);
if(container->is_end(*impl, id))
{
impl = container->next(id);
}
return *this;
}
ValueType& operator*() const { return impl->get(); }
friend bool operator==(polymorphic_iterator const& l,
polymorphic_iterator const& r)
{
if(l.impl == nullptr) return r.impl == nullptr;
if(r.impl == nullptr) return false;
return l.impl->equal( *(r.impl) );
}
friend bool operator!=(polymorphic_iterator const& l,
polymorphic_iterator const& r)
{
return not (l == r);
}
private:
std::unique_ptr< iterator_base<ValueType> > impl;
Container* container;
Id id;
friend Container;
polymorphic_iterator(Container* pc, Id pid, decltype(impl) p)
: impl( std::move(p) ), container(pc), id(std::move(pid))
{}
};
template<template<class> class Container, class Base>
class polymorphic_range_container
{
private:
using self = polymorphic_range_container;
struct IRange
{
using piterator = std::unique_ptr < iterator_base<Base> >;
virtual piterator begin() = 0;
virtual piterator end() = 0;
};
template<class It>
struct range : IRange
{
range(It p_begin, It p_end) : m_begin(p_begin), m_end(p_end) {}
using typename IRange::piterator;
piterator begin() override { return piterator{new iterator_impl(m_begin)}; }
piterator end() override { return piterator{new iterator_impl(m_end)}; }
private:
struct iterator_impl : iterator_base<Base>
{
iterator_impl(It p) : it(p) {}
virtual void advance(int i) override { std::advance(it, i); }
virtual Base& get() const override { return *it; }
virtual bool equal(iterator_base<Base> const& other) const override
{
iterator_impl const* pOther
= dynamic_cast<iterator_impl const*>(&other);
if(nullptr == pOther) return false;
else return it == pOther->it;
}
private:
It it;
};
iterator_impl m_begin;
iterator_impl m_end;
};
using container_type = Container< std::unique_ptr<IRange> >;
container_type ranges;
public:
template<class T>
void push_back(std::pair<T, T> p_range)
{
ranges.push_back( std::unique_ptr<IRange>{new range<T>(p_range.first, p_range.second)} );
}
using iterator = polymorphic_iterator<Base, self, typename container_type::const_iterator>;
iterator begin()
{
return iterator{this, ranges.cbegin(), ranges.front()->begin()};
}
iterator end()
{
return iterator{this, ranges.cend(), {nullptr}};
}
private:
friend iterator;
std::unique_ptr< iterator_base<Base> > next(typename container_type::const_iterator& p)
{
++p;
if(p == ranges.end()) return {nullptr};
else return (**p).begin();
}
bool is_end(iterator_base<Base> const& it, typename container_type::const_iterator const& id)
{
if(ranges.end() == id) return false;
else return (**id).end()->equal(it);
}
};