{"id":5850,"date":"2020-02-12T21:03:38","date_gmt":"2020-02-12T21:03:38","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-the-ranges-library\/"},"modified":"2023-09-27T16:55:50","modified_gmt":"2023-09-27T16:55:50","slug":"c-20-the-ranges-library","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-the-ranges-library\/","title":{"rendered":"C++20: The Ranges Library"},"content":{"rendered":"<p style=\"margin: 0px 0px 10px; color: #444444; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff;\">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 range library&#8217;s comfort and power are due to its functional ideas. Let me show you what that means.<\/p>\n<p><!--more--><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-8380 size-full\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges.png\" alt=\"\" width=\"979\" height=\"373\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges.png 979w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-300x114.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-768x293.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-705x269.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/06\/TimelineCpp20Ranges-845x321.png 845w\" sizes=\"auto, (max-width: 979px) 100vw, 979px\" \/><\/p>\n<p>Before I dive into the details, here is a first example of the ranges library:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ rangesFilterTransform.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;ranges&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> numbers <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>};\n  \n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> results <span style=\"color: #555555;\">=<\/span> numbers <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter([](<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">%<\/span> <span style=\"color: #ff6600;\">2<\/span> <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span>; })\n                           <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>transform([](<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> <span style=\"color: #ff6600;\">2<\/span>; });\n                           \n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> results) std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;     <span style=\"color: #0099ff; font-style: italic;\">\/\/ 4 8 12<\/span>\n\n}\n<\/pre>\n<\/div>\n<p>You have to read the expression from left to right.\u00a0The pipe symbol stands for function composition: First, all numbers can pass which are even (<span style=\"font-family: 'courier new', courier;\">std::views::filter([](int n){ return n % 2 == 0; }<\/span>)). Afterward, each remaining number is mapped to its double (<span style=\"font-family: 'courier new', courier;\">std::views::transform([](int n){ return n * 2; })<\/span>). The small example already shows two new ranges library features: Function composition, which operators on the entire container.<\/p>\n<p>Now you should be prepared for the details. Let&#8217;s go back to square one: ranges and views are concepts.<\/p>\n<h2>Range<\/h2>\n<ul>\n<li><span style=\"font-family: 'courier new', courier;\"><strong>std::range: <\/strong><\/span>A range is a group of items you can iterator over. It provides a begin iterator and an end sentinel. Of course, the containers of the STL are ranges.<\/li>\n<\/ul>\n<p>There exist refinements of <span style=\"font-family: 'courier new', courier;\">std::range<\/span>:<\/p>\n<ul>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::ranges::input_range:\u00a0<span style=\"color: #000000; font-family: DejaVuSans, 'DejaVu Sans', arial, sans-serif; font-size: 12.8px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">s<\/span><\/span><\/strong>pecifies a range whose iterator type satisfies input_iterator (can iterate from beginning to end at least once)<\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::ranges::output_range:\u00a0<span style=\"color: #000000; font-family: DejaVuSans, 'DejaVu Sans', arial, sans-serif; font-size: 12.8px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">s<\/span><\/span><\/strong>pecifies a range whose iterator type satisfies output_iterator<\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::ranges::forward_range:\u00a0<span style=\"font-family: 'courier new', courier;\"><span style=\"color: #000000; font-family: DejaVuSans, 'DejaVu Sans', arial, sans-serif; font-size: 12.8px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">s<\/span><\/span><\/span><\/strong>pecifies a range whose iterator type satisfies forward_iterator (can iterate from beginning to end more than once)<\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::ranges::bidirectional_range:\u00a0<span style=\"font-family: 'courier new', courier;\"><span style=\"color: #000000; font-family: DejaVuSans, 'DejaVu Sans', arial, sans-serif; font-size: 12.8px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">s<\/span><\/span><\/span><\/strong>pecifies a range whose iterator type satisfies bidirectional_iterator (can iterate forward and backward more than once)<\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::ranges::random_access_range:\u00a0<span style=\"font-family: 'courier new', courier;\"><span style=\"color: #000000; font-family: DejaVuSans, 'DejaVu Sans', arial, sans-serif; font-size: 12.8px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">s<\/span><\/span><\/span><\/strong>pecifies a range whose iterator type satisfies random_access_iterator (can jump in constant time to an arbitrary element with the index operator [])<\/li>\n<li><strong><span style=\"font-family: 'courier new', courier;\">std::ranges::contiguous_range:\u00a0<span style=\"font-family: 'courier new', courier;\"><span style=\"color: #000000; font-family: DejaVuSans, 'DejaVu Sans', arial, sans-serif; font-size: 12.8px; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: #ffffff; float: none;\">s<\/span><\/span><\/span><\/strong>pecifies a range whose iterator type satisfies contiguous_iterator (elements are stored consecutively in memory)<\/li>\n<\/ul>\n<p>The containers of the STL and<span style=\"font-family: 'courier new', courier;\"> std::string<\/span> model different concepts:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5847\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/RangeConcepts.png\" alt=\"RangeConcepts\" width=\"650\" height=\"397\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/RangeConcepts.png 1177w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/RangeConcepts-300x183.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/RangeConcepts-1024x626.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/RangeConcepts-768x469.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>A container supporting the <span style=\"font-family: 'courier new', courier;\">std::ranges::contiguous_range <\/span>concept supports all other concepts above, such as <span style=\"font-family: 'courier new', courier;\">std::ranges::random_access_range<\/span>, <span style=\"font-family: 'courier new', courier;\">std::ranges::bidirectional_range<\/span>, and<span style=\"font-family: 'courier new', courier;\"> std::ranges::input_range<\/span>. The same observation holds for all other ranges.<\/p>\n<p><span style=\"color: inherit; font-size: 35px;\">View<\/span><\/p>\n<ul>\n<li>You apply a View on a range and perform some operations. A view does not own data, and it&#8217;s time to copy, move, assignment its constant. Here is a quote from Eric Niebler&#8217;s <a href=\"https:\/\/github.com\/ericniebler\/range-v3\">range-v3 implementation<\/a>, which is the base for the C++20 ranges: &#8220;<em>Views are composable adaptations of ranges where the adaptation happens lazily as the view is iterated.<\/em>&#8220;<\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> numbers <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>};\n\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> results <span style=\"color: #555555;\">=<\/span> numbers <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter([](<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">%<\/span> <span style=\"color: #ff6600;\">2<\/span> <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span>; })\n                       <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>transform([](<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> <span style=\"color: #ff6600;\">2<\/span>; });\n<\/pre>\n<\/div>\n<p>In this code snippet, <span style=\"font-family: 'courier new', courier;\">numbers<\/span> are the range, and <span style=\"font-family: 'courier new', courier;\">std::views::filter<\/span> and <span style=\"font-family: 'courier new', courier;\">std::views::transform<\/span> are the views.<\/p>\n<p>Due to the power of views, C++20 allows programming in a functional style. <strong>Views can be combined and are lazy. <\/strong>l already presented two views, but we get more.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">std<span style=\"color: #555555;\">::<\/span>all_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>all               <span style=\"color: #0099ff; font-style: italic;\">\/\/ takes all elements<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>ref_view                                <span style=\"color: #0099ff; font-style: italic;\">\/\/ takes all elements of another view<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>filter_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter         <span style=\"color: #0099ff; font-style: italic;\">\/\/ takes the elements which satisfies the predicate<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>transform_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>transform   <span style=\"color: #0099ff; font-style: italic;\">\/\/ transforms each element<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>take_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take             <span style=\"color: #0099ff; font-style: italic;\">\/\/ takes the first N elements of another view<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>take_while_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take_while <span style=\"color: #0099ff; font-style: italic;\">\/\/ takes the elements of another view as long as the predicate returns true<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>drop_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>drop             <span style=\"color: #0099ff; font-style: italic;\">\/\/ skips the first N elements of another view<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>drop_while_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>drop_while <span style=\"color: #0099ff; font-style: italic;\">\/\/ skips the initial elements of another view until the predicate returns false<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>join_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>join             <span style=\"color: #0099ff; font-style: italic;\">\/\/ joins a view of ranges<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>split_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>split           <span style=\"color: #0099ff; font-style: italic;\">\/\/ splits a view by using a delimiter<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>common_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>common         <span style=\"color: #0099ff; font-style: italic;\">\/\/ converts a view into a std::common_range<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>reverse_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>reverse       <span style=\"color: #0099ff; font-style: italic;\">\/\/ iterates in reverse order<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>basic_istream_view, std<span style=\"color: #555555;\">::<\/span>istream_view   <span style=\"color: #0099ff; font-style: italic;\">\/\/ applies operator&gt;&gt; on the view<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>elements_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>elements     <span style=\"color: #0099ff; font-style: italic;\">\/\/ creates a view on the N-th element of tuples<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>keys_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>keys             <span style=\"color: #0099ff; font-style: italic;\">\/\/ creates a view on the first element of a pair-like values<\/span>\n\nstd<span style=\"color: #555555;\">::<\/span>values_view, std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>values         <span style=\"color: #0099ff; font-style: italic;\">\/\/ creates a view on the second elements of a pair-like values<\/span>\n<\/pre>\n<\/div>\n<p>You can generally use a view such as <span style=\"font-family: 'courier new', courier;\">std::views::transform<\/span> with the alternative name <span style=\"font-family: 'courier new', courier;\">std::transform_view<\/span>.\u00a0 I show the usage of various views as I go on.<\/p>\n<h2>Implementation Status<\/h2>\n<p>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 mentioned\u00a0 range-v3 implementation on the online <a href=\"https:\/\/wandbox.org\/\">Wandbox<\/a> or the <a href=\"https:\/\/godbolt.org\/\">Compiler Explorer <\/a>with the HEAD GCC. Here is what you have to do to translate my examples, such as<span style=\"color: #000000;\">\u00a0<span style=\"font-family: 'courier new', courier;\">rangesFilterTransform.cpp<\/span> to see it in action.<\/span><\/p>\n<ul>\n<li>Replace the namespaces<span style=\"font-family: 'courier new', courier;\"> std::views::<\/span> with <span style=\"font-family: 'courier new', courier;\">ranges::views::.<\/span><\/li>\n<li>Replace the header <span style=\"font-family: 'courier new', courier;\">&lt;ranges&gt;<\/span> with the header <span style=\"font-family: 'courier new', courier;\">&lt;range\/v3\/all.hpp&gt;<\/span>. For more details, study the documentation in\u00a0<a href=\"https:\/\/github.com\/ericniebler\/range-v3\">range-v3 implementation<\/a>.<\/li>\n<li>Compile your program with C++20 support:\u00a0<code>-std=c++2a.<\/code><\/li>\n<li>When you use <a href=\"https:\/\/godbolt.org\/\">Compiler Explorer<\/a>, you have to use the trunk version of the\u00a0<a href=\"https:\/\/github.com\/ericniebler\/range-v3\">range-v3 implementation<\/a>. The following picture should help you find the option.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5848\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/CompilerExplorer.png\" alt=\"CompilerExplorer\" width=\"500\" height=\"372\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/CompilerExplorer.png 684w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/CompilerExplorer-300x223.png 300w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/p>\n<p>Transforming the program get\u00a0<span style=\"font-family: 'courier new', courier;\">rangesFilterTransform.cpp<\/span> gives me the following program.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ rangesV3FilterTransform.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;range\/v3\/all.hpp&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;vector&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n\n    std<span style=\"color: #555555;\">::<\/span>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> numbers <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">4<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">6<\/span>};\n  \n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> results <span style=\"color: #555555;\">=<\/span> numbers <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter([](<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">%<\/span> <span style=\"color: #ff6600;\">2<\/span> <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span>; })\n                           <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>transform([](<span style=\"color: #007788; font-weight: bold;\">int<\/span> n){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> n <span style=\"color: #555555;\">*<\/span> <span style=\"color: #ff6600;\">2<\/span>; });\n                           \n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> v<span style=\"color: #555555;\">:<\/span> results) std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> v <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;    \n\n}\n<\/pre>\n<\/div>\n<p>Thanks to\u00a0<a href=\"https:\/\/wandbox.org\/\">Wandbox<\/a>, here is the output of the program without a faked source file:<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5849\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/02\/Wandbox.png\" alt=\"Wandbox\" width=\"120\" height=\"141\" \/><\/p>\n<p>I will use in my future posts the proposed C++20 syntax. Consequentially, you have to do the transformation step manually.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>In this post, I explained the basics of the ranges library. These basics enable me to write in my<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-functional-patterns-with-the-ranges-library\"> next post <\/a>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<a href=\"http:\/\/bit.ly\/3471cqH\"> big four of C++20<\/a>. Each part of the big four changes how we think and write modern C++.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 range library&#8217;s comfort and power are due to its functional [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":8380,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[413],"class_list":["post-5850","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-ranges"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5850"}],"version-history":[{"count":3,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5850\/revisions"}],"predecessor-version":[{"id":8384,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5850\/revisions\/8384"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/8380"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5850"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}