Я обнаружил, что пишу это совсем недавно:
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>();
}
И это позволяет мне писать такие вещи:
for (auto i: range<0, 10>()) {
// stuff with i
}
Теперь я знаю, что написанный мной код может быть не лучшим. И, возможно, есть способ сделать его более гибким и полезным. Но мне кажется, что что-то подобное следовало сделать частью стандарта.
Так это? Была ли добавлена какая-то новая библиотека для итераторов для диапазона целых чисел или, может быть, для общего диапазона вычисленных скалярных значений?
range
шаблонную функцию? Это не добавляет ничего к использованию, в которомrange_class
используется. Я имею в виду,range<0,10>()
иrange_class<0,10>()
выглядишь точно так же!Ответы:
В стандартной библиотеке C ++ его нет, но Boost.Range имеет boost :: counting_range , что, безусловно, соответствует требованиям. Вы также можете использовать boost :: irange , что немного более сфокусировано.
Библиотека диапазонов C ++ 20 позволит вам сделать это через
view::iota(start, end)
.источник
std::experimental::ranges
пространстве имен.range-v3
Я бы сказал, всегда была эталонной реализацией. Но теперь я считаю, что базовый диапазон диапазонов также недавно был включен в C ++ 20, так что мы действительноstd::
скоро его добавим! :-)Насколько мне известно, в C ++ 11 такого класса нет.
Во всяком случае, я попытался улучшить вашу реализацию. Я сделал его не шаблоном , так как не вижу никаких преимуществ в создании шаблона . Напротив, у него есть один серьезный недостаток: вы не можете создать диапазон во время выполнения, так как вам нужно знать аргументы шаблона во время самой компиляции.
Вот код:
Код теста:
Вывод:
10 11 12 13 14 15 16 17 18 19
Демо Onine .
источник
iterator
дляconst_iterator
,iterator
унаследовать отstd::iterator
иrange
реализоватьcbegin
иcend
. Да и ... почемуiterator::operator++
возвращает константную ссылку?[begin, end)
. @OP: +1 за каламбур на циклах на основе диапазона, что не является каламбуром :-)v++
которое должно возвращать значение до того, как произошла операция приращения. Я бы посоветовал изучить разницу между заявленным++i
иi++
где онi
находитсяint
.Я написал библиотеку, предназначенную
range
для той же цели, за исключением того, что это диапазон времени выполнения, а идея в моем случае пришла из Python. Я рассматривал версию во время компиляции, но, по моему скромному мнению, нет никаких реальных преимуществ, чтобы получить версию во время компиляции. Вы можете найти библиотеку на bitbucket, и она находится в разделе Boost License: Range . Это библиотека с одним заголовком, совместимая с C ++ 03 и работает как шарм с циклами for на основе диапазона в C ++ 11 :)Особенности :
Настоящий контейнер произвольного доступа со всеми прибамбасами!
Диапазоны можно сравнивать лексикографически.
Две функции
exist
(возвращает логическое значение) иfind
(возвращает итератор) для проверки существования числа.Библиотека прошла модульное тестирование с использованием CATCH .
Примеры базового использования, работа со стандартными контейнерами, работа со стандартными алгоритмами и работа с циклами на основе диапазона.
Вот одноминутное введение . Наконец, я приветствую любые предложения об этой крошечной библиотеке.
источник
Я обнаружил, что
boost::irange
это намного медленнее, чем канонический цикл с целыми числами. Поэтому я остановился на следующем гораздо более простом решении с использованием макроса препроцессора:Затем вы можете зацикливаться так:
Этот диапазон автоматически начинается с нуля. Его можно легко расширить, чтобы начать с заданного числа.
источник
for (RANGE(i, flag? n1: n2))
приведет к удивительным результатам, поскольку вы не выполнили одно из основных правил макросов Non-Evil, заключающееся в заключении в скобки всех ваших параметров (включая, в данном случае,b
). Ваш подход также не дает никакого преимущества в производительности по сравнению с немакросъемочным подходом, основанным на "объектах диапазона" (например , ответ Nawaz ).Вот более простая форма, которая мне нравится. Есть ли риски в моем подходе?
r_iterator
- это тип, который ведет себя, насколько это возможно, какlong int
. Поэтому многие операторы, такие как==
и++
, просто передаются вlong int
. Я «разоблачить» лежащий в основе длинного Int черезoperator long int
иoperator long int &
преобразование.( Изменить: - мы можем сделать методы
range
статическими вместо константы.)источник
Это может быть немного поздно, но я только что увидел этот вопрос и уже некоторое время использую этот класс:
Использование :
источник
вы пробовали использовать
В большинстве случаев отвечает всем требованиям.
Например
Обратите внимание, что printInt может быть заменен на лямбда в C ++ 0x. Также может быть еще один небольшой вариант этого использования (строго для random_iterator)
Только для итератора Fwd
источник
Вы можете легко сгенерировать возрастающую последовательность в C ++ 11, используя std :: iota ():
источник
range
Класс должен моделировать диапазон. Однако вы его буквально строите. Это пустая трата памяти и обращений к ней. Решение очень избыточно, потому что вектор не содержит реальной информации, кроме количества элементов и значения первого элемента (если он существует).