Python has that range
:
>>> range(10, -20, -3)
[10, 7, 4, 1, -2, -5, -8, -11, -14, -17]
I have this C++ implementation of exactly the same facility:
range.h:
/*
* File: range.h
* Author: Rodion "rodde" Efremov
* Version: (Nov 30, 2015)
*/
#ifndef RANGE_H
#define RANGE_H
#include <stdexcept>
namespace coderodde {
template<typename Int = int>
class range {
private:
Int m_start;
Int m_end;
Int m_step;
class range_iterator {
private:
Int m_value;
Int m_step;
size_t m_count;
public:
range_iterator(Int value,
Int step,
size_t count) : m_value{value},
m_step{step},
m_count{count} {}
int operator*() { return m_value; }
bool operator!=(range_iterator& other) { return m_count != other.m_count; }
void operator++() { m_value += m_step; ++m_count; }
};
public:
range(Int start, Int end, Int step) : m_start{start},
m_end{end},
m_step{step} {}
range(Int start, Int end) : range(start, end, 1) {}
range_iterator begin() { return range_iterator(m_start, m_step, 0); }
range_iterator end() {
if (m_step == 0) throw std::runtime_error("The step is zero.");
if (m_start <= m_end)
{
if (m_step < 0)
{
return range_iterator(0, 0, 0);
}
return range_iterator(m_start, m_step,
(m_end - m_start) / m_step +
(((m_end - m_start) % m_step) ? 1 : 0));
}
else
{
if (m_step > 0)
{
return range_iterator(0, 0, 0);
}
m_step = -m_step;
return range_iterator(m_start, m_step,
(m_start - m_end) / m_step +
(((m_start - m_end) % m_step) ? 1 : 0));
}
}
};
}
#endif /* RANGE_H */
With demo main.cpp:
#include <iostream>
#include "range.h"
using std::cin;
using std::cout;
using std::endl;
using coderodde::range;
int main(int argc, char* argv[])
{
while (true)
{
int start = 0;
int end = 0;
int step = 0;
cout << ">> ";
if (not (cin >> start >> end >> step))
{
break;
}
try
{
for (auto i : range<>(start, end, step))
{
cout << i << endl;
}
}
catch (std::runtime_error& err)
{
cout << "Error: " << err.what() << endl;
}
}
cout << "Bye!" << endl;
}
I tried hard to make my range
act exactly the same way is in Python (2.7). For instance, if step
is 0, an exception is thrown.
I do not have much experience in C++, so any critique is much appreciated.
make_range()
. That way you can use template type-deduction provided by functions to automatically get the correctly typed version ofrange
without having the ugly<>
at the end.for (auto i : make_range(start, end, step))
\$\endgroup\$ – Martin York Nov 30 '15 at 20:08xrange
rather thanrange
. That's not a problem, but worth noting. \$\endgroup\$ – Edward Nov 30 '15 at 20:13