Es ist durchaus machbar, aber ein Schmerz.
Sie wären besser dran, einen generatorbasierten Iterator zu erstellen, bei dem die Backing-Operation eine std::function< optional<T> >
ist. Hier ist ein Beispiel für einen solchen Generator-Iterator:
template<class T>
struct generator_iterator {
using difference_type=std::ptrdiff_t;
using value_type=T;
using pointer=T*;
using reference=T;
using iterator_category=std::input_iterator_tag;
std::optional<T> state;
std::function< std::optional<T>() > operation;
// we store the current element in "state" if we have one:
T operator*() const {
return *state;
}
// to advance, we invoke our operation. If it returns a nullopt
// we have reached the end:
generator_iterator& operator++() {
state = operation();
return *this;
}
generator_iterator operator++(int) {
auto r = *this;
++(*this);
return r;
}
// generator iterators are only equal if they are both in the "end" state:
friend bool operator==(generator_iterator const& lhs, generator_iterator const& rhs) {
if (!lhs.state && !rhs.state) return true;
return false;
}
friend bool operator!=(generator_iterator const& lhs, generator_iterator const& rhs) {
return !(lhs==rhs);
}
// We implicitly construct from a std::function with the right signature:
generator_iterator(std::function< std::optional<T>() > f):operation(std::move(f))
{
if (operation)
state = operation();
}
// default all special member functions:
generator_iterator(generator_iterator &&) =default;
generator_iterator(generator_iterator const&) =default;
generator_iterator& operator=(generator_iterator &&) =default;
generator_iterator& operator=(generator_iterator const&) =default;
generator_iterator() =default;
};
tun so mit Ihrem Java-like iterface noch getan werden kann.
Es gibt Lösungen in boost
, die dies erleichtern. Aber ich werde es "in rohen" schreiben, basierend auf C++ 17 Konzepten, die nach C++ 11 zurückportiert werden können, wenn Sie sie benötigen (oder aus Boost oder anderen Quellen extrahiert werden).
Sie würden einen Eingabe-Iterator generieren, da dies die Java-ähnliche Schnittstelle unterstützt.
Zuerst würde ich einen Helfer schreiben. Der Helfer würde eine optional< Iterator<V> >
und eine optional<V>
halten.
Es würde ++ unterstützen. ++ würde den Iterator weiterleiten und den Wert in optional<V>
lesen.
Es würde unäre *
unterstützen. *
würde den Wert im optionalen zurückgeben.
bool is_end()
gibt True zurück, wenn optional<Iterator<V>>
leer ist, oder !.hasNext()
.
==
gibt true wenn und nur wenn beide Argumente .is_end()
. !=
wäre einfach !
auf ==
angewendet.
Dieser Helper ist noch kein Iterator, hat aber die meisten Schlüsseloperationen.
Dann verwenden wir this poly_iterator welcher Typ löscht alles Iterator-like. Die Operationen, die wir oben auf dem Helfer geschrieben haben, sind ausreichend.
Dann schreiben wir eine Funktion, die eine Iterable<V>
und produziert eine range<poly_iterator<T>>
des Typs Löschklasse oben, mit dem Helper Pseudo-Iterator oben. Ein range<It>
ist eine Klasse, die wie folgt aussieht:
template<class It>
struct range {
It b; It e;
It begin() const { return b; }
It end() const { return e; }
};
und vielleicht andere Dienstprogramm Helfer.
Der Typ löschen Schritt könnte übersprungen werden, wenn Sie wählen. Erweitern Sie einfach den oben beschriebenen Helfer zu einem vollwertigen Eingabe-Iterator. Boost hat Helfer, die das leichter machen. Lassen Sie den Bereichsrückkehrer diesen vollwertigen Eingabe-Iterator zurückgeben. Ich hatte zufällig die poly_iterator<T>
in einer anderen Antwort herumliegen, und wenn Sie einen Hammer haben, sieht dieses Problem sicher wie ein Nagel aus.
Beachten Sie, dass der Code wirklich (Java) -ähnlich sein soll, wenn wir tatsächlich (intelligente) Zeiger auf die Objekte haben wollen, die nicht kopiert werden.
Sie werden dies nicht tun können. Ein C++ - Iterator und ein Java-Iterator sind unterschiedliche Konzepte. – NathanOliver
Versuchen Sie nicht, Java-Code in C++ zu schreiben. Java-Code hat genug Probleme, wenn er in Java geschrieben ist. –
Wenn man fragt, wie man einen Java-Iterator zum Erzeugen eines C++ - Iterators "umsetzt", fragt man sich, wie viel Eis man braucht, um ein Feuer zu starten. –