Для тех, кому нравится std::views::iota
ответ Cigien, но не работает на C ++ 20 или выше, довольно просто реализовать упрощенную и облегченную версию std::views::iota
совместимогоc ++ 11 или выше.
Все, что для этого требуется:
- Базовый тип LegacyInputIterator (что-то, что определяет
operator++
и operator*
), который содержит целое значение (например, int
)
- Некий "диапазонный" класс, который имеет
begin()
и end()
возвращает вышеуказанные итераторы. Это позволит ему работать в for
циклах на основе диапазона
Упрощенная версия этого может быть:
#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};
}
Я определил выше, constexpr
где это поддерживается, но для более ранних версий C ++, таких как C ++ 11/14, вам может потребоваться удалить, constexpr
если это не разрешено в этих версиях.
Приведенный выше шаблон позволяет следующему коду работать в версиях до C ++ 20:
for (int const i : iota(0, 10))
{
std::cout << i << " ";
i = 42;
}
Что будет генерировать ту же сборку, что и решение C ++ 20, std::views::iota
и классическое for
решение -loop при оптимизации.
Это работает с любыми компиляторами, совместимыми с C ++ 11 (например, с подобными компиляторами gcc-4.9.4
), и по-прежнему производит почти идентичную сборку с базовым for
аналогом -loop.
Примечание . iota
Вспомогательная функция предназначена только для обеспечения паритета функций с std::views::iota
решением C ++ 20 ; но на самом деле вы также можете напрямую построить iota_range{...}
вместо вызова iota(...)
. Первый вариант представляет собой простой способ обновления, если пользователь желает в будущем перейти на C ++ 20.