Ronnie Ronnie - 1 month ago 14
C++ Question

How to write a declarative for loop c++14

Is there a way to write a declarative style for loop in C++14

for(int i = 0; i < 10; i+=2) {
// ... some code
}


The closest I have found is using boost is

for(auto i : irange(1,10,2)){
// .... some code
}


Is there a c++14/17 standards way of achieving the same effect?

I was trying std::make_integer_sequence() as a possible starting point, but couldn't quite figure it out.

Answer

There is not a standard way of iterating over a numerical range as you desire. C++14 however allows you to create your own utilities very easily.


Approach one: numerical range.

Here's an unoptimized quickly-hacked-together example:

template <typename T>
struct num_range_itr
{
    T _value, _step;

    num_range_itr(T value, T step) 
        : _value{value}, _step{step} 
    {
    }

    auto operator*() const { return _value; }
    auto operator++() { _value += _step; }

    auto operator==(const num_range_itr& rhs) const { return _value == rhs._value; }
    auto operator!=(const num_range_itr& rhs) const { return !(*this == rhs); }
};

template <typename T>
struct num_range
{
    T _start, _end, _step;

    num_range(T start, T end, T step) 
        : _start{start}, _end{end}, _step{step} 
    {
    }

    auto begin() const { return num_range_itr<T>{_start, _step}; }
    auto end() const { return num_range_itr<T>{_end, _step}; }
};

template <typename T>
auto make_range(T start, T end, T step = 1)
{
    return num_range<T>{start, end, step};
}

The code above can be used as follows:

for(auto i : make_range(0, 10, 2))
{
    std::cout << i << " ";
}

// Prints: 0 2 4 6 8

Approach two: higher-order function.

Here's an unoptimized quickly-hacked-together example:

template <typename T, typename TF>
auto for_range(T start, T end, T step, TF f)
{
    for(auto i = start; i < end; i += step)
    {
        f(i);
    }

    return f;
}

The code above can be used as follows:

for_range(0, 10, 2, [](auto i){ std::cout << i << " "; });

// Prints: 0 2 4 6 8

The code can be found on wandbox.

If you want to use these utilities in real projects, you need to carefully write them in order to support multiple types safely, avoid unintentional signed/unsigned conversions, avoid invalid ranges, and make sure they get optimized away.