C++20: The Ranges Library


Thanks to the ranges library in C++20, working with the Standard Template Library (STL) will become much more comfortable and powerful. The algorithms of the ranges library are lazy, can work directly on the container and can easily be composed. To make it short: The comfort and the power of the ranges library are due to its functional ideas. Let me show you what that means.



Before I dive into the details. Here is a first example of the ranges library:


// rangesFilterTransform.cpp

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

int main() {

    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
    auto results = numbers | std::views::filter([](int n){ return n % 2 == 0; })
                           | std::views::transform([](int n){ return n * 2; });
    for (auto v: results) std::cout << v << " ";     // 4 8 12



You have to read the expression from left to right. The pipe symbol stands for function composition: First, all numbers can pass which are even (std::views::filter([](int n){ return n % 2 == 0; })). Afterwards, each remaining number is mapped to its double (std::views::transform([](int n){ return n * 2; })). The small example shows already two new features of the ranges library: Function composition which operators on the entire container.  

Now you should be prepared for the details. Let's go back to square one: ranges and views are concepts.


  • std::range: A range is a group of items that you can iterator over. It provides a begin iterator and an end sentinel. Of course, the containers of the STL are ranges.

There exist refinements of std::range

  • std::ranges::input_range: specifies a range whose iterator type satisfies input_iterator (can iterate from begin to end at least once)
  • std::ranges::output_range: specifies a range whose iterator type satisfies output_iterator 
  • std::ranges::forward_range: specifies a range whose iterator type satisfies forward_iterator (can iterate from begin to end more than once)
  • std::ranges::bidirectional_range: specifies a range whose iterator type satisfies bidirectional_iterator (can iterate forward and backward more than once)
  • std::ranges::random_access_range: specifies a range whose iterator type satisfies random_access_iterator (can jump in constant time to an arbitrary element with the index operator [])
  • std::ranges::contiguous_range: specifies a range whose iterator type satisfies contiguous_iterator (elements are stored consecutively in memory)

 The containers of the STL and std::string model different concepts:



A container supporting the std::ranges::contiguous_range concept, supports all other concepts above such as std::ranges::random_access_range, std::ranges::bidirectional_range, and std::ranges::input_range. The same observation holds for all other ranges. 


  • A View is something that you apply on a range and performs some operation. A view does not own data and it's time to copy, move, assignment its constant. Here is a quote from Eric Nieblers range-v3 implementation which is the base for the C++20 ranges: "Views are composable adaptations of ranges where the adaptation happens lazily as the view is iterated."


std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

auto results = numbers | std::views::filter([](int n){ return n % 2 == 0; })
                       | std::views::transform([](int n){ return n * 2; });


In this code-snippet, numbers is the range and std::views::filter and std::views::transform are the views. 

Due to the power of views, C++20 allows programming in a functional style. Views can be combined and are lazy. l already presented two views but we get more. 


std::all_view, std::views::all               // takes all elements

std::ref_view                                // takes all elements of another view

std::filter_view, std::views::filter         // takes the elements which satisfies the predicate

std::transform_view, std::views::transform   // transforms each element

std::take_view, std::views::take             // takes the first N elements of another view

std::take_while_view, std::views::take_while // takes the elements of another view as long as the predicate returns true

std::drop_view, std::views::drop             // skips the first N elements of another view

std::drop_while_view, std::views::drop_while // skips the initial elements of another view until the predicate returns false

std::join_view, std::views::join             // joins a view of ranges

std::split_view, std::views::split           // splits a view by using a delimiter

std::common_view, std::views::common         // converts a view into a std::common_range

std::reverse_view, std::views::reverse       // iterates in reverse order

std::basic_istream_view, std::istream_view   // applies operator>> on the view

std::elements_view, std::views::elements     // creates a view on the N-th element of tuples

std::keys_view, std::views::keys             // creates a view on the first element of a pair-like values

std::values_view, std::views::values         // creates a view on the second elements of a pair-like values


In general, you can use a view such as std::views::transform with the alternative name std::transform_view.  I show the usage of various views as I go on.

Implementation Status

As far as I know, there is no implementation of the ranges library now (February 2020) available. This is not an issue. You can use the already mentioned  range-v3 implementation on the online compiler Wandbox or the Compiler Explorer with the HEAD GCC. Here is what you have to do to translate my examples such as rangesFilterTransform.cpp to see it in action.

  • Replace the namespaces std::views:: with ranges::views::.
  • Replace the header <ranges> with the header <range/v3/all.hpp>. For more details, study the documentation in range-v3 implementation.
  • Compile your program with C++20 support: -std=c++2a.
  • When you use the Compiler Explorer, you have to use the trunk version of the range-v3 implementation. The following picture should help you find the option.


Transforming the program get rangesFilterTransform.cpp gives me the following program. 


// rangesV3FilterTransform.cpp

#include <iostream>
#include <range/v3/all.hpp>
#include <vector>

int main() {

    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
    auto results = numbers | ranges::views::filter([](int n){ return n % 2 == 0; })
                           | ranges::views::transform([](int n){ return n * 2; });
    for (auto v: results) std::cout << v << " ";    



Thanks to Wandbox, here is the output of the program without a faked source file:Wandbox

I use in my future posts the proposed C++20 syntax. Consequentially, you have to do the transformation step manually. 

What's next?

In this post, I explained the basics to the ranges library. These basics enable me to write in my next post about their power. The ranges library extends C++20 with two new concepts: function composition and lazy evaluation. This is the reason, ranges belong to the big four of C++20. Each part of the big four changes the way we think, and we write modern C++.



Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, Marko, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, espkk, Louis St-Amour, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Neil Wang, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Tobi Heideman, Daniel Hufschläger, Red Trip, Alexander Schwarz, Tornike Porchxidze, Alessandro Pezzato, Evangelos Denaxas, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Dimitrov Tsvetomir, Leo Goodstadt, Eduardo Velasquez, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, and Michael Young.


Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, and Bhushan Ivatury.



My special thanks to Embarcadero CBUIDER STUDIO FINAL ICONS 1024 Small



I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.

Bookable (Online)


Standard Seminars (English/German)

Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.


Contact Me

Modernes C++,






My Newest E-Books

Course: Modern C++ Concurrency in Practice

Course: C++ Standard Library including C++14 & C++17

Course: Embedded Programming with Modern C++

Course: Generic Programming (Templates)

Course: C++ Fundamentals for Professionals

Interactive Course: The All-in-One Guide to C++20

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code


Today 3720

Yesterday 5806

Week 3720

Month 173137

All 7440977

Currently are 156 guests and no members online

Kubik-Rubik Joomla! Extensions

Latest comments