{"id":6361,"date":"2022-05-19T11:53:53","date_gmt":"2022-05-19T11:53:53","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/the-ranges-library-in-c-20-a-deep-dive\/"},"modified":"2023-09-27T16:58:12","modified_gmt":"2023-09-27T16:58:12","slug":"the-ranges-library-in-c-20-a-deep-dive","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/the-ranges-library-in-c-20-a-deep-dive\/","title":{"rendered":"The Ranges Library in C++20: More Details"},"content":{"rendered":"<p>Working with the Standard Template Library (STL) is much more comfortable and powerful thanks to the ranges library. The algorithms of the ranges library are lazy, can work directly on the container, and can quickly be composed. But there is more to it:<\/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 deep into the ranges library in C++20, I want to recap in a few sentences the three main features of the ranges: The algorithms of the ranges can directly operate on the container, evaluate their arguments lazily, and can be composed.<\/p>\n<h2>Direct on the Container<\/h2>\n<p>The classical algorithms of the Standard Template Library (STL) are sometimes a little inconvenient. They need a beginning and an end iterator. This is often more than you want to write.<\/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: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ sortClassical.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;algorithm&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&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> myVec{<span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">4<\/span>};\n    std<span style=\"color: #555555;\">::<\/span>sort(myVec.begin(), myVec.end());     <em><span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/em>\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> myVec) 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, -3, 0, 5, 7<\/span>\n\n}\n<\/pre>\n<\/div>\n<div>\n<div>Wouldn&#8217;t it be nice if\u00a0<code>std::sort<\/code> (line 1) could be executed on the entire container? Thanks to the ranges library, this is possible in C++20.<\/div>\n<\/div>\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: 0px; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ sortRanges.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;algorithm&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;iostream&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> myVec{<span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">3<\/span>, <span style=\"color: #ff6600;\">5<\/span>, <span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #ff6600;\">7<\/span>, <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">4<\/span>};\n    std<span style=\"color: #555555;\">::<\/span>ranges<span style=\"color: #555555;\">::<\/span>sort(myVec);                  <em><span style=\"color: #0099ff;\">\/\/ (1)<\/span><\/em>\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> myVec) 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, -3, 0, 5, 7<\/span>\n\n}\n<\/pre>\n<\/div>\n<p><code>std::ranges::sort<\/code> (line 1) operates directly on the container.<\/p>\n<h2>Lazy Evaluation<\/h2>\n<div>\n<div><code><a href=\"https:\/\/en.cppreference.com\/w\/cpp\/ranges\/iota_view\">std::views::iota<\/a><\/code> is a range factory for creating a sequence of elements by successively incrementing an initial value. This sequence can be finite or infinite. The elements of the range factory are only created when needed.<\/div>\n<div><\/div>\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;\">\/\/ lazyRanges.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;ranges&gt;<\/span>\n\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\n                                    \n    \n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> i<span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(<span style=\"color: #ff6600;\">1<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span>, <span style=\"color: #ff6600;\">1<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">010<\/span>)) {     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;  \n    }\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n                                         \n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> i<span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(<span style=\"color: #ff6600;\">1<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span>)                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n                <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take(<span style=\"color: #ff6600;\">10<\/span>)) {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;  \n    }\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> i<span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(<span style=\"color: #ff6600;\">1<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span>)                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n                <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take_while([](<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i) { <span style=\"color: #006699; font-weight: bold;\">return<\/span> i <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">1<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">010<\/span>; } )) {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;  \n    }\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"<\/span><span style=\"color: #cc3300; font-weight: bold;\">\\n\\n<\/span><span style=\"color: #cc3300;\">\"<\/span>;\n\n}\n<\/pre>\n<\/div>\n<\/div>\n<p>The small program shows the difference between creating a finite data stream (line 1) and an infinite data stream (lines 2 and 3). When you create an infinite data stream, you need a boundary condition. Line (2) uses the view <code>std::views::take(10)<\/code>, and line 3, the view <code>std::views::take_while<\/code>.<code> std::views::take_while<\/code> requires a predicate. This is an ideal fit for a lambda expression:\u00a0 <code>[](auto i) { return i &lt; 1'000'010; }. <\/code>Since C++14, you can use single quotes as separators in integer literals: <code>1'000'010.<\/code> All three <code>std::views::ranges<\/code> calls produce the same numbers.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6359\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/lazyRanges.png\" alt=\"lazyRanges\" width=\"650\" height=\"239\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/lazyRanges.png 808w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/lazyRanges-300x111.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/lazyRanges-768x283.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/h2>\n<p>I already used the pipe operator (<code>|<\/code>) in this example for function composition. Let&#8217;s go one step further.<\/p>\n<h2>Function Composition<\/h2>\n<p>The following program <code>primesLazy.cpp<\/code> creates the first ten prime numbers starting with one million.<\/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;\">\/\/ primesLazy.cpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\n<span style=\"color: #009999;\">#include &lt;ranges&gt;<\/span>\n\n\n<span style=\"color: #007788; font-weight: bold;\">bool<\/span> <span style=\"color: #cc00ff;\">isPrime<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> i) {\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> j<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">2<\/span>; j<span style=\"color: #555555;\">*<\/span>j <span style=\"color: #555555;\">&lt;=<\/span> i; <span style=\"color: #555555;\">++<\/span>j){\n        <span style=\"color: #006699; font-weight: bold;\">if<\/span> (i <span style=\"color: #555555;\">%<\/span> j <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">0<\/span>) <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">false<\/span>;\n    }\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> <span style=\"color: #336666;\">true<\/span>;\n}\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>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n                                         \n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> odd <span style=\"color: #555555;\">=<\/span> [](<span style=\"color: #007788; font-weight: bold;\">int<\/span> i){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> i <span style=\"color: #555555;\">%<\/span> <span style=\"color: #ff6600;\">2<\/span> <span style=\"color: #555555;\">==<\/span> <span style=\"color: #ff6600;\">1<\/span>; };\n\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #007788; font-weight: bold;\">int<\/span> i<span style=\"color: #555555;\">:<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(<span style=\"color: #ff6600;\">1<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #aa0000; background-color: #ffaaaa;\">'<\/span><span style=\"color: #ff6600;\">000<\/span>) <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter(odd) \n                                            <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter(isPrime) \n                                            <span style=\"color: #555555;\">|<\/span> std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take(<span style=\"color: #ff6600;\">10<\/span>)) {\n        std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>;  \n    }\n\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\n\n}\n<\/pre>\n<\/div>\n<div>You have to read the function composition from left to right: I create an infinite data stream starting with 1&#8217;000&#8217;000 (<code>std::views::iota(1'000'000)<\/code>) and apply two filters. Each filter needs a predicate. The first filter lets the odd element pass (<code>std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter(odd)<\/code>), and the second filter lets the prime numbers pass (<code>std<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>filter(isPrime)<\/code>). To end the infinite data stream, I stop after ten numbers (<code>std::views::take(10)<\/code>).\u00a0 Finally, here are the first ten prime numbers starting with one million.<\/div>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-6360\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/primesLazy.png\" alt=\"primesLazy\" width=\"650\" height=\"153\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/primesLazy.png 808w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/primesLazy-300x71.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2022\/05\/primesLazy-768x181.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>You may ask: Who starts the processing of this data pipeline? Now, it goes from right to left. The data sink (<code>std::views::take(10)<\/code>) want to have the next value and ask its predecessor. This request goes on until the range-based for-loop as the data source can produce one number.<\/p>\n<p>This was my short recap. When you want to read more about the ranges library, read my previous posts:<\/p>\n<ul>\n<li><a href=\"http:\/\/bit.ly\/2V8Fbqz\">The Ranges Library<\/a><\/li>\n<li><a href=\"http:\/\/bit.ly\/32iY77s\">Functional Pattern with the Ranges Library<\/a><\/li>\n<li><a href=\"http:\/\/bit.ly\/2TyfqNX\">Pythonic with the Ranges Library<\/a><\/li>\n<li><a href=\"http:\/\/bit.ly\/2wI2z3G\">Pythons range Function, the Second<\/a><\/li>\n<li><a href=\"http:\/\/bit.ly\/2QhUQAw\">Pythons map Function<\/a><\/li>\n<\/ul>\n<p>Now, it&#8217;s time to write about something new.<\/p>\n<h2><code>std<\/code> Algorithms versus <code>std::ranges<\/code> Algorithms<\/h2>\n<p>The algorithms of the\u00a0<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/algorithm\">algorithm library<\/a> and the\u00a0<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/memory\">memory libray<\/a> have ranges pendants. They start with the namespace <code>std::ranges<\/code>. The <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/header\/numeric\">numeric library<\/a> does not have a ranges pendant. Now, you may have the question: Should I use the classical <code>std<\/code> or new <code>std::ranges<\/code> algorithm?<\/p>\n<div>\n<div>Let me start with a comparison of the classical <code>std::sort<\/code> and the new <code>std::ranges::sort.<\/code> First, here are the various overloads of <code>std::sort<\/code> and <code>std::ranges::sort<\/code>.<\/div>\n<\/div>\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: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">RandomIt<\/span> <span style=\"color: #555555;\">&gt;<\/span>\nconstexpr <span style=\"color: #007788; font-weight: bold;\">void<\/span> sort( RandomIt first, RandomIt last );\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">ExecutionPolicy<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">RandomIt<\/span> <span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> sort( ExecutionPolicy<span style=\"color: #555555;\">&amp;&amp;<\/span> policy,\n           RandomIt first, RandomIt last );\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">RandomIt<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Compare<\/span> <span style=\"color: #555555;\">&gt;<\/span>\nconstexpr <span style=\"color: #007788; font-weight: bold;\">void<\/span> sort( RandomIt first, RandomIt last, Compare comp );\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">ExecutionPolicy<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">RandomIt<\/span>, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Compare<\/span> <span style=\"color: #555555;\">&gt;<\/span>\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> sort( ExecutionPolicy<span style=\"color: #555555;\">&amp;&amp;<\/span> policy,\n           RandomIt first, RandomIt last, Compare comp );\n<\/pre>\n<\/div>\n<div>\n<div><code>std::sort<\/code> has four overloads in C++20. Let&#8217;s see what I can deduce from the names of the function declarations. All four overloads take a range given by a begin and end iterator. The iterators must be random access iterators. The first and third overloads are declared as <code>constexpr<\/code> and can run at compile time. The second and fourth overload require an <a href=\"https:\/\/www.modernescpp.com\/(https:\/www.modernescpp.com\/index.php\/parallel-algorithms-of-the-stl-with-gcc\">execution policy<\/a>. The execution policy lets you specify if the program should run sequentially, parallel, or vectorized.<\/div>\n<div><\/div>\n<div>The last two overloads, lines 8 and 11, lets you specify the sorting strategy. <code>Compare<\/code> has to be a binary predicate. A binary predicate is a callable that takes two arguments and returns something convertible to a <code>bool<\/code>.<\/div>\n<div><\/div>\n<div>\n<div>\n<div>I assume my analysis reminded you of concepts. But there is a big difference. The names in the\u00a0<code>std::sort<\/code> do not stand for concepts but only for documentation purposes. In <code>std::ranges::sort<\/code> the names are concepts.<\/div>\n<div><\/div>\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: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>random_access_iterator I, std<span style=\"color: #555555;\">::<\/span>sentinel_for<span style=\"color: #555555;\">&lt;<\/span>I<span style=\"color: #555555;\">&gt;<\/span> S,\n         <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Comp<\/span> <span style=\"color: #555555;\">=<\/span> ranges<span style=\"color: #555555;\">::<\/span>less, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Proj<\/span> <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>identity<span style=\"color: #555555;\">&gt;<\/span>\nrequires std<span style=\"color: #555555;\">::<\/span>sortable<span style=\"color: #555555;\">&lt;<\/span>I, Comp, Proj<span style=\"color: #555555;\">&gt;<\/span>\nconstexpr I sort(I first, S last, Comp comp <span style=\"color: #555555;\">=<\/span> {}, Proj proj <span style=\"color: #555555;\">=<\/span> {});\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span>ranges<span style=\"color: #555555;\">::<\/span>random_access_range R, <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Comp<\/span> <span style=\"color: #555555;\">=<\/span> ranges<span style=\"color: #555555;\">::<\/span>less, \n          <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Proj<\/span> <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>identity<span style=\"color: #555555;\">&gt;<\/span>\nrequires std<span style=\"color: #555555;\">::<\/span>sortable<span style=\"color: #555555;\">&lt;<\/span>ranges<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">iterator_t<\/span><span style=\"color: #555555;\">&lt;<\/span>R<span style=\"color: #555555;\">&gt;<\/span>, Comp, Proj<span style=\"color: #555555;\">&gt;<\/span>\nconstexpr ranges<span style=\"color: #555555;\">::<\/span><span style=\"color: #007788; font-weight: bold;\">borrowed_iterator_t<\/span><span style=\"color: #555555;\">&lt;<\/span>R<span style=\"color: #555555;\">&gt;<\/span> sort(R<span style=\"color: #555555;\">&amp;&amp;<\/span> r, Comp comp <span style=\"color: #555555;\">=<\/span> {}, Proj proj <span style=\"color: #555555;\">=<\/span> {});\n<\/pre>\n<\/div>\n<div>\n<div>\n<aside>\n<div><\/div>\n<div>When you study the two overloads, you notice that it takes a sortable range <code>R<\/code> (lines 2 and 4), either given by a begin iterator and end sentinel (line 1) or by a <code>ranges::random_access_range<\/code> (line 3). The iterator and the range must support random access. Additionally, the overloads take a predicate Comp, and a projection <code>Proj<\/code>. The predicate <code>Comp<\/code> uses by default <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/functional\/ranges\/less\">ranges::less<\/a>, and the projection <code>Proj<\/code> of the identity <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/functional\/identity\">std::identity<\/a>. A projection is a mapping of a set into a subset. In C++20 <code>std::ranges::sort<\/code> does not support execution policies.<\/div>\n<h2>What&#8217;s next?<\/h2>\n<div>In my next post, I will analyze the overloads of std::ranges::sort deeper and write about projections and sentinels.<\/div>\n<div><\/div>\n<div><\/div>\n<div><\/div>\n<\/aside>\n<div><\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Working with the Standard Template Library (STL) is much more comfortable and powerful thanks to the ranges library. The algorithms of the ranges library are lazy, can work directly on the container, and can quickly be composed. But there is more to it:<\/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-6361","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\/6361","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=6361"}],"version-history":[{"count":2,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6361\/revisions"}],"predecessor-version":[{"id":8396,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/6361\/revisions\/8396"}],"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=6361"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=6361"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=6361"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}