Ich habe das erst vor kurzem geschrieben:
template <long int T_begin, long int T_end>
class range_class {
public:
class iterator {
friend class range_class;
public:
long int operator *() const { return i_; }
const iterator &operator ++() { ++i_; return *this; }
iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
bool operator ==(const iterator &other) const { return i_ == other.i_; }
bool operator !=(const iterator &other) const { return i_ != other.i_; }
protected:
iterator(long int start) : i_ (start) { }
private:
unsigned long i_;
};
iterator begin() const { return iterator(T_begin); }
iterator end() const { return iterator(T_end); }
};
template <long int T_begin, long int T_end>
const range_class<T_begin, T_end>
range()
{
return range_class<T_begin, T_end>();
}
Und das erlaubt mir, solche Dinge zu schreiben:
for (auto i: range<0, 10>()) {
// stuff with i
}
Jetzt weiß ich, dass das, was ich geschrieben habe, vielleicht nicht der beste Code ist. Und vielleicht gibt es eine Möglichkeit, es flexibler und nützlicher zu machen. Aber es scheint mir, als hätte so etwas Teil des Standards sein sollen.
So ist es? Wurde eine neue Bibliothek für Iteratoren über einen Bereich von Ganzzahlen oder einen generischen Bereich von berechneten Skalarwerten hinzugefügt?
range
Vorlagenfunktion zu schreiben ? Es fügt der Verwendung, in derrange_class
es verwendet wird , nichts hinzu . Ich meinerange<0,10>()
undrange_class<0,10>()
sehe genauso aus!Antworten:
Die C ++ - Standardbibliothek hat keine, aber Boost.Range hat boost :: count_range , was sicherlich qualifiziert. Sie können auch boost :: irange verwenden , das etwas fokussierter ist.
Mit der Bereichsbibliothek von C ++ 20 können Sie dies über tun
view::iota(start, end)
.quelle
std::experimental::ranges
Namespace geschafft hat.range-v3
war immer eine Art Referenzimplementierung, würde ich sagen. Aber jetzt glaube ich, dass das grundlegende Sortiment kürzlich auch in C ++ 20 gewählt wurde, also werden wir es tatsächlichstd::
bald bekommen! :-)Soweit ich weiß, gibt es in C ++ 11 keine solche Klasse.
Wie auch immer, ich habe versucht, Ihre Implementierung zu verbessern. Ich habe es ohne Vorlage erstellt , da ich keinen Vorteil darin sehe , es als Vorlage zu erstellen . Im Gegenteil, es hat einen großen Nachteil: Sie können den Bereich nicht zur Laufzeit erstellen, da Sie die Vorlagenargumente zur Kompilierungszeit selbst kennen müssen.
Hier ist der Code:
Testcode:
Ausgabe:
10 11 12 13 14 15 16 17 18 19
Onine Demo .
quelle
iterator
zu verwendenconst_iterator
, voniterator
abzuleitenstd::iterator
und zurange
implementierencbegin
undcend
. Oh und ... warumiterator::operator++
gibt eine konstante Referenz zurück?[begin, end)
. @OP: +1 für das Wortspiel auf bereichsbasierten Schleifen, das kein Wortspiel ist :-)v++
das den Wert zurückgeben soll, bevor die Inkrementoperation stattgefunden hat. Ich würde Ihnen raten, den Unterschied zwischen++i
undi++
woi
erklärt wird, zu seinint
.Ich habe eine Bibliothek geschrieben, die
range
genau den gleichen Zweck hat, außer dass es sich um einen Laufzeitbereich handelt, und die Idee in meinem Fall kam von Python. Ich habe eine Version zur Kompilierungszeit in Betracht gezogen, aber meiner bescheidenen Meinung nach gibt es keinen wirklichen Vorteil, die Version zur Kompilierungszeit zu erhalten. Sie finden die Bibliothek auf bitbucket und sie befindet sich unter Boost License: Range . Es ist eine Ein-Header-Bibliothek, die mit C ++ 03 kompatibel ist und wie ein Zauber mit bereichsbasierter for-Schleife in C ++ 11 funktioniert :)Eigenschaften :
Ein wahrer Direktzugriffsbehälter mit allem Schnickschnack!
Bereiche können lexikographisch verglichen werden.
Zwei Funktionen
exist
(gibt bool zurück) undfind
(gibt den Iterator zurück), um die Existenz einer Zahl zu überprüfen.Die Bibliothek wird mit CATCH getestet .
Beispiele für die grundlegende Verwendung, Arbeiten mit Standardcontainern, Arbeiten mit Standardalgorithmen und Arbeiten mit einem auf Schleifen basierenden Bereich.
Hier ist eine einminütige Einführung . Schließlich begrüße ich jeden Vorschlag zu dieser winzigen Bibliothek.
quelle
Ich fand, dass
boost::irange
das viel langsamer war als die kanonische Ganzzahlschleife. Deshalb habe ich mich mit einem Präprozessor-Makro für die folgende viel einfachere Lösung entschieden:Dann können Sie folgende Schleife ausführen:
Dieser Bereich beginnt automatisch bei Null. Es kann leicht erweitert werden, um von einer bestimmten Nummer auszugehen.
quelle
for (RANGE(i, flag? n1: n2))
überraschenden Ergebnissen führt, da Sie eine der Grundregeln für nicht böse Makros nicht befolgt haben, nämlich alle Ihre Parameter in Klammern zu setzen (in diesem Fall auchb
). Ihr Ansatz bietet auch keinen Leistungsvorteil gegenüber dem nicht auf Makros basierenden Ansatz "Range Object" (z. B. Nawaz 'Antwort ).Hier ist eine einfachere Form, die für mich gut funktioniert. Gibt es irgendwelche Risiken in meinem Ansatz?
r_iterator
ist ein Typ, der sich so weit wie möglich wie a verhältlong int
. Daher gehen viele Operatoren wie==
und++
einfach auf dielong int
. Ich 'exponiere' das zugrunde liegende Long Int über dieoperator long int
undoperator long int &
Conversions.( Bearbeiten: - Wir können die Methoden der
range
statischen anstelle von const machen.)quelle
Das mag etwas spät sein, aber ich habe gerade diese Frage gesehen und benutze diese Klasse jetzt schon eine Weile:
Verwendung :
quelle
hast du versucht mit
Meistens passt die Rechnung.
Z.B
Beachten Sie, dass printInt OFC in C ++ 0x durch ein Lambda ersetzt werden kann. Eine weitere kleine Variation dieser Verwendung könnte sein (ausschließlich für random_iterator).
Für Fwd nur Iterator
quelle
Mit std :: iota () können Sie in C ++ 11 ganz einfach eine aufsteigende Sequenz generieren:
quelle
range
Klasse soll den Bereich modellieren. Sie konstruieren es jedoch buchstäblich. Das ist eine Verschwendung von Speicher und Speicherzugriffen. Die Lösung ist hochgradig redundant, da der Vektor außer der Anzahl der Elemente und dem Wert des ersten Elements (falls vorhanden) keine realen Informationen enthält.