Für alle, die Cigiens std::views::iota
Antwort mögen, aber nicht in C ++ 20 oder höher arbeiten, ist es ziemlich einfach, eine vereinfachte und leichtgewichtige Version von std::views::iota
kompatibel zu implementierenc ++ 11 oder höher.
Alles was es erfordert ist:
- Ein grundlegender " LegacyInputIterator " -Typ (etwas, der definiert
operator++
und operator*
), der einen ganzzahligen Wert umschließt (z. B. ein int
)
- Eine "range" -ähnliche Klasse, die die obigen Iteratoren hat
begin()
und end()
zurückgibt. Dadurch kann es in bereichsbasierten for
Schleifen arbeiten
Eine vereinfachte Version davon könnte sein:
#include <iterator>
class counting_iterator
{
public:
using iterator_category = std::input_iterator_tag;
using value_type = int;
using reference = int;
using pointer = int*;
using difference_type = std::ptrdiff_t;
constexpr explicit counting_iterator(int x) : m_value{x}{}
constexpr counting_iterator(const counting_iterator&) = default;
constexpr counting_iterator& operator=(const counting_iterator&) = default;
constexpr reference operator*() const { return m_value; }
constexpr pointer operator->() const { return &m_value; }
constexpr counting_iterator& operator++() {
m_value++;
return (*this);
}
constexpr counting_iterator operator++(int) {
const auto copy = (*this);
++(*this);
return copy;
}
constexpr bool operator==(const counting_iterator& other) const noexcept {
return m_value == other.m_value;
}
constexpr bool operator!=(const counting_iterator& other) const noexcept {
return m_value != other.m_value;
}
private:
int m_value;
};
struct iota_range
{
int first;
int last;
constexpr counting_iterator begin() const { return counting_iterator{first}; }
constexpr counting_iterator end() const { return counting_iterator{last}; }
};
constexpr iota_range iota(int first, int last)
{
return iota_range{first, last};
}
Ich habe oben definiert, constexpr
wo es unterstützt wird, aber für frühere Versionen von C ++ wie C ++ 11/14 müssen Sie möglicherweise entfernen, constexpr
wo es in diesen Versionen nicht legal ist, um dies zu tun.
Mit dem obigen Boilerplate kann der folgende Code in Pre-C ++ 20 verwendet werden:
for (int const i : iota(0, 10))
{
std::cout << i << " ";
i = 42;
}
Die den Willen erzeugen gleiche Anordnung wie die C ++ 20 - std::views::iota
Lösung und der klassischen for
-loop Lösung , wenn optimiert.
Dies funktioniert mit allen C ++ 11-kompatiblen Compilern (z. B. Compilern wie gcc-4.9.4
) und erzeugt immer noch eine nahezu identische Assembly wie ein Basic- for
Loop-Gegenstück.
Hinweis: Die iota
Hilfsfunktion dient nur der Feature-Parität mit der C ++ 20- std::views::iota
Lösung. aber realistisch könnte man auch direkt ein konstruieren iota_range{...}
anstatt aufzurufen iota(...)
. Ersteres bietet nur einen einfachen Upgrade-Pfad, wenn ein Benutzer in Zukunft zu C ++ 20 wechseln möchte.