dnl
dnl

Reputation: 155

Why use std::ranges algorithms over regular algorithms?

cppreference states:

The ranges library is an extension and generalization of the algorithms and iterator libraries that makes them more powerful by making them composable and less error-prone.

The library creates and manipulates range views, lightweight objects that indirectly represent iterable sequences (ranges).

It mentions using range views, which are, as cppreference states:

The range concept defines the requirements of a type that allows iteration over its elements by providing an iterator and sentinel that denote the elements of the range.

But from an outside perspective, it just seems like a wrapper of an iterator with a concept. So the main question is:

Upvotes: 10

Views: 2186

Answers (3)

Drew Dormann
Drew Dormann

Reputation: 63947

The constrained algorithms in namespace std::ranges are niebloids, which means - among other things - that you can pass the entire algorithm as a function parameter, or otherwise assign it to a variable.

void do_work( auto algorithm, Foo::Type &a, Foo::Type &b )
{
    algorithm( a, b );
}

I could pass std::ranges::swap as the first parameter to this function. a and b will get swapped correctly.

But std::swap? That won't compile! And if you worked to get it to compile, you still won't know if it's doing the right thing.

First, std::swap is a template and you can't pass a template as a function parameter. Second, std::swap isn't aware if there might be a better match Foo::swap function. The niebloid does.

Upvotes: 1

Jarod42
Jarod42

Reputation: 218138

what are the problems with using regular iterators that ranges library solves (code examples will be appreciated)?

It might avoid some mistakes with temporary container:

// assuming std::vector<int> compute_vector();

// Following is wrong begin and end refers to different (temporary) containers
const bool KO = std::is_sorted(compute_vector().begin(),
                               compute_vector().end()); // WRONG

// Here all is ok.
const bool OK = std::ranges::is_sorted(compute_vector());

Upvotes: 6

thebugger
thebugger

Reputation: 185

The second one will allow you to pipe other operations present only in the ranges header, which is much better for composability:

#include <ranges>
#include <vector>
#include <algorithm>
#include <iostream>

int main()
{
    const auto v = std::vector{ 1, 2, 3, 4, 5 };
    const auto is_odd = [](const auto n){ return n % 2 == 1; };
    const auto square = [](const auto n){ return n * n; };
    const auto print = [](const auto n){ std::cout << n << " ";};
    std::ranges::for_each(
        v | std::ranges::views::filter(is_odd) | std::ranges::views::transform(square),
        print); // prints: 1 9 25 
}

Upvotes: 9

Related Questions