Per qualche background del perché sto facendo questa domanda ecco un esempio. In python il metodo chain
concatena un numero arbitrario di intervalli insieme e li rende in uno senza fare copie. Ecco un collegamento nel caso in cui non lo capisci. Ho deciso di implementare la catena in c ++ usando modelli variadic. Per quanto ne so, l'unico modo per fare un iteratore per catena che andrà al contenitore successivo è che ogni iteratore sappia della fine del contenitore (ho pensato a una sorta di hack in cui !=
è chiamato contro la fine saprà di andare al prossimo contenitore, ma il primo modo sembrava più facile e più sicuro e più versatile).
La mia domanda è se c'è qualcosa di intrinsecamente sbagliato in un iteratore che conosce la propria fine, il mio codice è in c ++ ma questo può essere indipendente dal linguaggio poiché molte lingue hanno iteratori.
#ifndef CHAIN_HPP
#define CHAIN_HPP
#include "iterator_range.hpp"
namespace iter {
template <typename ... Containers>
struct chain_iter;
template <typename Container>
struct chain_iter<Container> {
private:
using Iterator = decltype(((Container*)nullptr)->begin());
Iterator begin;
const Iterator end;//never really used but kept it for consistency
public:
chain_iter(Container & container, bool is_end=false) :
begin(container.begin()),end(container.end()) {
if(is_end) begin = container.end();
}
chain_iter & operator++()
{
++begin;
return *this;
}
auto operator*()->decltype(*begin)
{
return *begin;
}
bool operator!=(const chain_iter & rhs) const{
return this->begin != rhs.begin;
}
};
template <typename Container, typename ... Containers>
struct chain_iter<Container,Containers...>
{
private:
using Iterator = decltype(((Container*)nullptr)->begin());
Iterator begin;
const Iterator end;
bool end_reached = false;
chain_iter<Containers...> next_iter;
public:
chain_iter(Container & container, Containers& ... rest, bool is_end=false) :
begin(container.begin()),
end(container.end()),
next_iter(rest...,is_end) {
if(is_end)
begin = container.end();
}
chain_iter & operator++()
{
if (begin == end) {
++next_iter;
}
else {
++begin;
}
return *this;
}
auto operator*()->decltype(*begin)
{
if (begin == end) {
return *next_iter;
}
else {
return *begin;
}
}
bool operator !=(const chain_iter & rhs) const {
if (begin == end) {
return this->next_iter != rhs.next_iter;
}
else
return this->begin != rhs.begin;
}
};
template <typename ... Containers>
iterator_range<chain_iter<Containers...>> chain(Containers& ... containers)
{
auto begin =
chain_iter<Containers...>(containers...);
auto end =
chain_iter<Containers...>(containers...,true);
return
iterator_range<chain_iter<Containers...>>(begin,end);
}
}
#endif //CHAIN_HPP