{"id":5860,"date":"2020-03-06T06:44:12","date_gmt":"2020-03-06T06:44:12","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-more-pythonic-with-the-ranges-library\/"},"modified":"2023-09-27T16:54:16","modified_gmt":"2023-09-27T16:54:16","slug":"c-20-more-pythonic-with-the-ranges-library","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-more-pythonic-with-the-ranges-library\/","title":{"rendered":"C++20: Pythons range Function, the Second"},"content":{"rendered":"<p>In my last post, <a href=\"http:\/\/bit.ly\/2TyfqNX\">C++20: Pythonic with the Ranges Library<\/a>, I started my experiment to implement the beloved Python functions <span style=\"font-family: 'courier new', courier;\">range<\/span> and <span style=\"font-family: 'courier new', courier;\">filter<\/span> in C++. Due to two very interesting comments to my last post, I revisit the function <span style=\"font-family: 'courier new', courier;\">range<\/span>.<\/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>Admittedly, it took me quite a time to become comfortable with the ranges library, but the effort paid off. You will see why.<\/p>\n<p>I got a few fascinating remarks about my range implementation in my last post. Therefore, I have to visit it once more.<\/p>\n<h2><span style=\"font-family: 'courier new', courier;\">range<\/span><\/h2>\n<p>As a short reminder, the call <span style=\"font-family: 'courier new', courier;\">range(begin, end, step)<\/span> generates in Python 2 a list of all integers from <span style=\"font-family: 'courier new', courier;\">begin<\/span> to <span style=\"font-family: 'courier new', courier;\">end<\/span> in <span style=\"font-family: 'courier new', courier;\">stepsize<\/span> steps. <span style=\"font-family: 'courier new', courier;\">begin<\/span> is inclusive, and the end is exclusive. <span style=\"font-family: 'courier new', courier;\">step<\/span> is per default 1.<\/p>\n<h3>Over-Engineering<\/h3>\n<p>My last <span style=\"font-family: 'courier new', courier;\">range<\/span> implementation of the last was over-engineered, as one of my German readers remarked. The following code snippet shows the over-engineered and the improved version.<\/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>vector<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span> range(<span style=\"color: #007788; font-weight: bold;\">int<\/span> begin, <span style=\"color: #007788; font-weight: bold;\">int<\/span> end, <span style=\"color: #007788; font-weight: bold;\">int<\/span> stepsize <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>) {\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> result{};\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (begin <span style=\"color: #555555;\">&lt;<\/span> end) {                                     \n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> boundary <span style=\"color: #555555;\">=<\/span> [end](<span style=\"color: #007788; font-weight: bold;\">int<\/span> i){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> i <span style=\"color: #555555;\">&lt;<\/span> end; };    \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> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(begin)               <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>stride(stepsize) \n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take_while(boundary)) {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n            result.push_back(i);\n        }\n    }\n    <span style=\"color: #006699; font-weight: bold;\">else<\/span> {                                                \n        begin<span style=\"color: #555555;\">++<\/span>;\n        end<span style=\"color: #555555;\">++<\/span>;\n        stepsize <span style=\"color: #555555;\">*=<\/span> <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>;\n        <span style=\"color: #006699; font-weight: bold;\">auto<\/span> boundary <span style=\"color: #555555;\">=<\/span> [begin](<span style=\"color: #007788; font-weight: bold;\">int<\/span> i){ <span style=\"color: #006699; font-weight: bold;\">return<\/span> i <span style=\"color: #555555;\">&lt;<\/span> begin; }; \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> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(end)                \n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take_while(boundary)      \n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>reverse \n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>stride(stepsize)) {\n            result.push_back(i);\n        }\n    }\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> result;\n}  \n\nstd<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> range(<span style=\"color: #007788; font-weight: bold;\">int<\/span> begin, <span style=\"color: #007788; font-weight: bold;\">int<\/span> end, <span style=\"color: #007788; font-weight: bold;\">int<\/span> stepsize <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>) {\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> result{};\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (begin <span style=\"color: #555555;\">&lt;<\/span> end) {\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> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(begin, end)         <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n                 <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>stride(stepsize)) {\n            result.push_back(i);\n        }\n    }\n    <span style=\"color: #006699; font-weight: bold;\">else<\/span> {\n        begin<span style=\"color: #555555;\">++<\/span>;\n        end<span style=\"color: #555555;\">++<\/span>;\n        stepsize <span style=\"color: #555555;\">*=<\/span> <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>;\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> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(end, begin)         \n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>reverse \n                  <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>stride(stepsize)) {\n            result.push_back(i);\n        }\n    }\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> result;\n}\n<\/pre>\n<\/div>\n<p>I removed the boundary condition (line 1) in the first implementation and changed the infinite number generator <span style=\"font-family: 'courier new', courier;\">ranges::views::iota(begin)<\/span> (line 2) to a finite number generator <span style=\"font-family: 'courier new', courier;\">ranges::view::iota(begin, end)<\/span> (line 3). Consequentially, I did the same in the <span style=\"font-family: 'courier new', courier;\">else<\/span> branch.<\/p>\n<h3>From <span style=\"font-family: 'courier new', courier;\">range<\/span> to <span style=\"font-family: 'courier new', courier;\">xrange<\/span><\/h3>\n<p>The presented <span style=\"font-family: 'courier new', courier;\">range<\/span> function is eager.\u00a0It generates a <span style=\"font-family: 'courier new', courier;\">std::vector&lt;int&gt;<\/span>. \u00a0Aleksei Guzev reminded me that Python 2 also has a lazy\u00a0<span style=\"font-family: 'courier new', courier;\">xrange<\/span> function which corresponds to the Python 3 <span style=\"font-family: 'courier new', courier;\">range<\/span> function. He is right. I&#8217;m sufficiently comfortable with the ranges library to apply functional concepts to C++. If you are puzzled by the terms eager and lazy, read my previous post, <a href=\"http:\/\/bit.ly\/32iY77s\">C++20: Functional Patterns with the Ranges Library<\/a>.<\/p>\n<p>The following example shows a lazy range variant, which I called, consequentially, <span style=\"font-family: 'courier new', courier;\">xrange<\/span>.<\/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;\">\/\/ xrange.hpp<\/span>\n\n<span style=\"color: #009999;\">#include &lt;range\/v3\/all.hpp&gt;<\/span>\n\n<span style=\"color: #006699; font-weight: bold;\">template<\/span> <span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">long<\/span> <span style=\"color: #007788; font-weight: bold;\">long<\/span> Begin, <span style=\"color: #007788; font-weight: bold;\">long<\/span> <span style=\"color: #007788; font-weight: bold;\">long<\/span> End<span style=\"color: #555555;\">&gt;<\/span>           <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n<span style=\"color: #006699; font-weight: bold;\">auto<\/span> xrange(<span style=\"color: #007788; font-weight: bold;\">int<\/span> stepsize <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>) {\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> constexpr (Begin <span style=\"color: #555555;\">&lt;<\/span> End) {                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(Begin, End)      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n               <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>stride(stepsize); \n    }\n    <span style=\"color: #006699; font-weight: bold;\">else<\/span> {\n        <span style=\"color: #007788; font-weight: bold;\">long<\/span> <span style=\"color: #007788; font-weight: bold;\">long<\/span> end  <span style=\"color: #555555;\">=<\/span> End <span style=\"color: #555555;\">+<\/span> <span style=\"color: #ff6600;\">1<\/span>;                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n        <span style=\"color: #007788; font-weight: bold;\">long<\/span> <span style=\"color: #007788; font-weight: bold;\">long<\/span> begin <span style=\"color: #555555;\">=<\/span> Begin <span style=\"color: #555555;\">+<\/span> <span style=\"color: #ff6600;\">1<\/span>;                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n        stepsize <span style=\"color: #555555;\">*=<\/span> <span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>; \n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>iota(end, begin)      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n               <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>reverse \n               <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>stride(stepsize);\n    }\n}\n<\/pre>\n<\/div>\n<p>Implementing the lazy <span style=\"font-family: 'courier new', courier;\">xrange<\/span> function is way more complicated than the previous eager <span style=\"font-family: 'courier new', courier;\">range<\/span> function. But the added complexity pays off. The following numbers correspond to the numbers in the source code snippet.<\/p>\n<ol>\n<li>The <span style=\"font-family: 'courier new', courier;\">xrange<\/span> function returns not a <span style=\"font-family: 'courier new', courier;\">std::vector&lt;int&gt;<\/span> but a composition of views. I let the compiler deduce the return type with auto to ease my job. OK, but the return type caused the first challenge. The return types of the <span style=\"font-family: 'courier new', courier;\">if<\/span> and <span style=\"font-family: 'courier new', courier;\">else<\/span> branch diver.\u00a0A function with different return types is not valid in C++.<\/li>\n<li>To overcome this issue, I used a C++17 feature: <span style=\"font-family: 'courier new', courier;\">constexpr if.<\/span>\u00a0<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/if\"><span style=\"font-family: 'courier new', courier;\">constexpr if<\/span><\/a> allows conditional compilation. When the expression i<span style=\"font-family: 'courier new', courier;\">f constexpr (Begin &lt; End))<\/span> becomes true, the <span style=\"font-family: 'courier new', courier;\">if<\/span> branch is compiled; if not, the <span style=\"font-family: 'courier new', courier;\">else<\/span> branch. To be valid, <span style=\"font-family: 'courier new', courier;\">Begin<\/span> and <span style=\"font-family: 'courier new', courier;\">End<\/span> have to be constant expressions.<\/li>\n<li><span style=\"font-family: 'courier new', courier;\">Begin<\/span> and <span style=\"font-family: 'courier new', courier;\">End<\/span> are now non-type template parameters which makes it possible to use them in a <span style=\"font-family: 'courier new', courier;\">constexpr if<\/span> (line 2) expression. I used a non-type template parameter of type <span style=\"font-family: 'courier new', courier;\">long long<\/span> to deal with big numbers. You read in a few sentences why.<\/li>\n<li>Constant expressions such as <span style=\"font-family: 'courier new', courier;\">Begin<\/span> and <span style=\"font-family: 'courier new', courier;\">End<\/span> can not be modified. Consequentially, I introduced the variables <span style=\"font-family: 'courier new', courier;\">end<\/span> and <span style=\"font-family: 'courier new', courier;\">begin<\/span> to adapt the boundaries for the <span style=\"font-family: 'courier new', courier;\">ranges::views::iota<\/span> call.<\/li>\n<\/ol>\n<p>Let&#8217;s try it out.<\/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;\">\/\/ range.cpp<\/span>\n\n<span style=\"color: #009999;\">#include \"xrange.hpp\"<\/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        \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> std<span style=\"color: #555555;\">::<\/span>endl;\n\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> res <span style=\"color: #555555;\">=<\/span> xrange<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">10<\/span><span style=\"color: #555555;\">&gt;<\/span>();                    <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i<span style=\"color: #555555;\">:<\/span> res) 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    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    res <span style=\"color: #555555;\">=<\/span> xrange<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">50<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #ff6600;\">5<\/span>);                        <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i<span style=\"color: #555555;\">:<\/span> res) 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    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;\">auto<\/span> res2 <span style=\"color: #555555;\">=<\/span> xrange<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">20<\/span>, <span style=\"color: #ff6600;\">10<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">1<\/span>);                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i<span style=\"color: #555555;\">:<\/span> res2) 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    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    res2 <span style=\"color: #555555;\">=<\/span> xrange<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">50<\/span>, <span style=\"color: #ff6600;\">10<\/span><span style=\"color: #555555;\">&gt;<\/span>(<span style=\"color: #555555;\">-<\/span><span style=\"color: #ff6600;\">5<\/span>);                     <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i<span style=\"color: #555555;\">:<\/span> res2) 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    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    res <span style=\"color: #555555;\">=<\/span> xrange<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">1'<\/span><span style=\"color: #ff6600;\">000'<\/span><span style=\"color: #ff6600;\">000'<\/span><span style=\"color: #ff6600;\">000'<\/span><span style=\"color: #ff6600;\">000'<\/span><span style=\"color: #ff6600;\">000'<\/span><span style=\"color: #ff6600;\">000<\/span><span style=\"color: #555555;\">&gt;<\/span>();  <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ for (auto i: res) std::cout &lt;&lt; i &lt;&lt; \" \";    \/\/ (6)<\/span>\n    \n    \n                                                   <span style=\"color: #0099ff; font-style: italic;\">\/\/ (7)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i<span style=\"color: #555555;\">:<\/span> res <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take(<span style=\"color: #ff6600;\">10<\/span>)) 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    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: #0099ff; font-style: italic;\">\/\/ (8)<\/span>\n    <span style=\"color: #006699; font-weight: bold;\">for<\/span> (<span style=\"color: #006699; font-weight: bold;\">auto<\/span> i<span style=\"color: #555555;\">:<\/span> res <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>drop_while([](<span style=\"color: #007788; font-weight: bold;\">int<\/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: #ff6600;\">000'<\/span><span style=\"color: #ff6600;\">000<\/span>; })\n                     <span style=\"color: #555555;\">|<\/span> ranges<span style=\"color: #555555;\">::<\/span>views<span style=\"color: #555555;\">::<\/span>take_while([](<span style=\"color: #007788; font-weight: bold;\">int<\/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: #ff6600;\">000'<\/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<p>Lines (1) &#8211; (4) show that the <span style=\"font-family: 'courier new', courier;\">xrange<\/span> function works as the previous <span style=\"font-family: 'courier new', courier;\">range<\/span> function. The only difference is that the function arguments become template arguments. I have to kill the program when I want to have all numbers up to a quintillion (line 6).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5858\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrangeBreak.png\" alt=\"xrangeBreak\" width=\"650\" height=\"292\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrangeBreak.png 1121w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrangeBreak-300x135.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrangeBreak-1024x459.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrangeBreak-768x345.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>Using tics for numbers (<span style=\"font-family: 'courier new', courier;\">1&#8217;000&#8217;000&#8217;000&#8217;000&#8217;000&#8217;000<\/span>) (line 5) is valid since C++14 and makes the big numbers easier to read. I should not be so eager but lazy. If I ask only for ten numbers (line 7) or between <span style=\"font-family: 'courier new', courier;\">1&#8217;000&#8217;000<\/span> and <span style=\"font-family: 'courier new', courier;\">1&#8217;000&#8217;010<\/span> (line 8) the program works like a charm. Only the numbers are generated that are requested.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5859\" style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrange.png\" alt=\"xrange\" width=\"500\" height=\"243\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrange.png 893w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrange-300x146.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2020\/03\/xrange-768x373.png 768w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/h2>\n<h2>What&#8217;s next?<\/h2>\n<p>As I already promised in my last post <a href=\"http:\/\/bit.ly\/2TyfqNX\">C++20: Pythonic with the Ranges Library<\/a>, I present in my <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-pythons-map-function\">next post<\/a> Python&#8217;s <span style=\"font-family: 'courier new', courier;\">map<\/span> function. <span style=\"font-family: 'courier new', courier;\">map<\/span> empowers you to apply a function to sequences. For convenience reasons, I combine the <span style=\"font-family: 'courier new', courier;\">map<\/span> and <span style=\"font-family: 'courier new', courier;\">filter<\/span> functions into one function.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last post, C++20: Pythonic with the Ranges Library, I started my experiment to implement the beloved Python functions range and filter in C++. Due to two very interesting comments to my last post, I revisit the function range.<\/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":[412,413],"class_list":["post-5860","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-python","tag-ranges"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5860","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=5860"}],"version-history":[{"count":3,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5860\/revisions"}],"predecessor-version":[{"id":8388,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5860\/revisions\/8388"}],"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=5860"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5860"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5860"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}