{"id":7967,"date":"2023-08-07T06:06:38","date_gmt":"2023-08-07T06:06:38","guid":{"rendered":"https:\/\/www.modernescpp.com\/?p=7967"},"modified":"2023-08-23T17:00:15","modified_gmt":"2023-08-23T17:00:15","slug":"c23-more-small-pearls","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c23-more-small-pearls\/","title":{"rendered":"C++23: More Small Pearls"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">With the static multidimensional subscript and call operator, the C++23 core language has more to offer.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/Cpp23AutoStatic-1030x579.png\" alt=\"\" class=\"wp-image-7969\" style=\"width:773px;height:434px\" width=\"773\" height=\"434\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/Cpp23AutoStatic-1030x579.png 1030w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/Cpp23AutoStatic-300x169.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/Cpp23AutoStatic-768x432.png 768w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/Cpp23AutoStatic-705x397.png 705w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/Cpp23AutoStatic.png 1280w\" sizes=\"auto, (max-width: 773px) 100vw, 773px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><code>auto(x)<\/code> and <code>auto{x}<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In my last post, &#8220;<a href=\"https:\/\/www.modernescpp.com\/index.php\/c23-the-small-pearls-in-the-core-language\/\" data-type=\"URL\" data-id=\"https:\/\/www.modernescpp.com\/index.php\/c23-the-small-pearls-in-the-core-language\/\">C++23: The Small Pearls in the Core Language<\/a>&#8220;, I gave a concise explanation of <code>auto(x) <\/code>and <code>auto{x}<\/code>: The calls <code>auto(x) <\/code>and <code>auto{x}<\/code> cast <code>x<\/code> into a prvalue as if passing <code>x<\/code> as a function argument by value.<code> auto(x)<\/code> and<code> auto{x}<\/code> perform a decay copy. I also explained a decay copy. This explanation of<code> auto(x)<\/code> and <code>auto{x}<\/code> was short, too short. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/twitter.com\/atomgalaxy\">Ga\u0161per A\u017eman<\/a> tweeted me about it:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/GazarTweet.png\" alt=\"\" class=\"wp-image-7972\" style=\"width:524px;height:120px\" width=\"524\" height=\"120\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/GazarTweet.png 699w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/GazarTweet-300x69.png 300w\" sizes=\"auto, (max-width: 524px) 100vw, 524px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Ga\u0161per is an active member of the C++ standardization committee: In C++, he participated in the standardization of <a href=\"https:\/\/www.modernescpp.com\/index.php\/c23-deducing-this\/\" data-type=\"URL\" data-id=\"https:\/\/www.modernescpp.com\/index.php\/c23-deducing-this\/\">&#8220;deducing this&#8221;<\/a>, and  &#8220;<a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/enum\" data-type=\"URL\" data-id=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/enum\">using enum<\/a>&#8220;. Additionally, Ga\u0161per is involved in the <a href=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2021\/p2279r0.html\" data-type=\"URL\" data-id=\"https:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2021\/p2279r0.html\">customization points <\/a>effort, the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-a-detour-to-contracts\/\" data-type=\"URL\" data-id=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-a-detour-to-contracts\/\">contracts<\/a> effort, and is an assistant chair of the networking study group.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I asked Ga\u0161per if he wants to write a few words about the implications of<code> auto(x)<\/code> and <code>auto{x}<\/code> on function interface design. I&#8217;m happy to present his answer. The explanation is embedded into the source code.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #009999\">#include &lt;vector&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;string&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;memory&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;utility&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;array&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;algorithm&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;charconv&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;cstring&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ To achieve a design that improves local reasoning, we should<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ design algorithm interfaces to not mutate their arguments if<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ at all possible.<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Unfortunately, this is often at odds with the efficiency of<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ the implementation of the algorithm.<\/span>\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ This comes up in many areas. A few examples include:<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ - matrix algorithms, where implementations often require that arguments do not alias<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ - state machines, where testing is far easier if we can produce a completely new state<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ - range algorithms such as the below example<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ - immutable maps and sets (see the immer library: https:\/\/github.com\/arximboldi\/immer)<\/span>\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ For clarity, let us consider a small example.<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Our data structure will be a vector of integers<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Our family of algorithms will be &quot;sorted&quot; and &quot;uniqued&quot;<\/span>\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ In c++20 (if we ignore ranges - we are trying to illustrate an approach),<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ we would probably design the interface by taking by value and returning<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ by value<\/span>\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ (helpers)<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> read_input(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) <span style=\"color: #555555\">-&gt;<\/span> 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>;\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> write_output(<span style=\"color: #007788; font-weight: bold\">int<\/span>) <span style=\"color: #555555\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold\">void<\/span>;\n\n<span style=\"color: #006699; font-weight: bold\">namespace<\/span> traditional {\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> sorted(std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> x) <span style=\"color: #555555\">-&gt;<\/span> std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> {\n    std<span style=\"color: #555555\">::<\/span>sort(x.begin(), x.end());\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> x;\n}\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> uniqued(std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> x) <span style=\"color: #555555\">-&gt;<\/span> std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> {\n    x.erase(std<span style=\"color: #555555\">::<\/span>unique(x.begin(), x.end()), x.end());\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> x;\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ This pattern leads to the following usage pattern<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> usage(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\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> uniqued(sorted(read_input(argc, argv)))) {\n        write_output(i);\n    };\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ This is good, but sooner or later someone will want to refactor this<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ code like this<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> refactor(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input <span style=\"color: #555555\">=<\/span> read_input(argc, argv);\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> uniqued(sorted(input))) {\n        write_output(i);\n    };\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ can you spot the bug? Non-professionals often don&#39;t!<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ If you work with researchers and scientists, this kind of mistake<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ is ubiquitous, and leads to serious, serious slow-downs that are often<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ difficult to find if not spotted immediately.<\/span>\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ What can we do? We should ask the compiler to issue an error, of course.<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ We can do this by explicitly asking for an rvalue reference instead of <\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ taking by value.<\/span>\n}\n\n<span style=\"color: #006699; font-weight: bold\">namespace<\/span> require_moves {\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> sorted(std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;&amp;&amp;<\/span> x) <span style=\"color: #555555\">-&gt;<\/span> std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> {\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                    ^^ new<\/span>\n    std<span style=\"color: #555555\">::<\/span>sort(x.begin(), x.end());\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> x;\n}\n\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> uniqued(std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;&amp;&amp;<\/span> x) <span style=\"color: #555555\">-&gt;<\/span> std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;<\/span> {\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                     ^^ new<\/span>\n    x.erase(std<span style=\"color: #555555\">::<\/span>unique(x.begin(), x.end()), x.end());\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> x;\n}\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> read_input(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) <span style=\"color: #555555\">-&gt;<\/span> 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>;\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> write_output(<span style=\"color: #007788; font-weight: bold\">int<\/span>) <span style=\"color: #555555\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold\">void<\/span>;\n\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">usage<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ compiles unchanged, and has the same performance<\/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> uniqued(sorted(read_input(argc, argv)))) {\n        write_output(i);\n    };\n}\n\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">refactor<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input <span style=\"color: #555555\">=<\/span> read_input(argc, argv);\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> uniqued(sorted(std<span style=\"color: #555555\">::<\/span>move(input)))) {\n        <span style=\"color: #0099FF; font-style: italic\">\/\/                       ^^^^^^^^^^     ^ required, does not compile without it!<\/span>\n        write_output(i);\n    };\n}\n\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> print_diff(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> <span style=\"color: #006699; font-weight: bold\">const<\/span><span style=\"color: #555555\">&amp;<\/span>, 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> <span style=\"color: #006699; font-weight: bold\">const<\/span><span style=\"color: #555555\">&amp;<\/span>) <span style=\"color: #555555\">-&gt;<\/span> <span style=\"color: #007788; font-weight: bold\">void<\/span>;\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ of course, now we have a problem. What if we actually needed the copy?<\/span>\n<span style=\"color: #009999\">#if defined(TRY_1)<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">check_is_sorted_and_uniqued<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input <span style=\"color: #555555\">=<\/span> read_input(argc, argv);\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> sorted_and_uniqued <span style=\"color: #555555\">=<\/span> uniqued(sorted(input));\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                                ^^^^^^ no matching function for call to sorted<\/span>\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (input <span style=\"color: #555555\">!=<\/span> sorted_and_uniqued) {\n        print_diff(input, sorted_and_uniqued);\n        exit(<span style=\"color: #FF6600\">1<\/span>);\n    }\n    exit(<span style=\"color: #FF6600\">0<\/span>);\n}\n<span style=\"color: #009999\">#elif defined(TRY_2)<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ we can work around this by making a copy explicitly<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">check_is_sorted_and_uniqued<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input <span style=\"color: #555555\">=<\/span> read_input(argc, argv);\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input_copy <span style=\"color: #555555\">=<\/span> input; <span style=\"color: #0099FF; font-style: italic\">\/\/ &lt;- sad face; requires its own statement, ugly<\/span>\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> sorted_and_uniqued <span style=\"color: #555555\">=<\/span> uniqued(sorted(std<span style=\"color: #555555\">::<\/span>move(input_copy)));\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (input <span style=\"color: #555555\">!=<\/span> sorted_and_uniqued) {\n        print_diff(input, sorted_and_uniqued);\n        exit(<span style=\"color: #FF6600\">1<\/span>);\n    }\n    exit(<span style=\"color: #FF6600\">0<\/span>);\n}\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Don&#39;t you think this is bad user experience, though?<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Of course it is. We just wanted to make copies explicit, not near-impossible.<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ The standard library specification has had a name for this for a long time:<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ they call it DECAY_COPY, which is literally what happens, but is inscruitable<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ jargon.<\/span>\n<span style=\"color: #009999\">#elif defined(TRY_3)<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Some smart users have tried and defined their own accompanying function<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ to std::move for this:<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">decay_copyish<\/span>(<span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;&amp;<\/span> x) { <span style=\"color: #006699; font-weight: bold\">return<\/span> std<span style=\"color: #555555\">::<\/span>forward<span style=\"color: #555555\">&lt;<\/span>decltype(x)<span style=\"color: #555555\">&gt;<\/span>(x); }\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ If we have that, we could write our check_is_sorted_and_uniqued without the named copy:<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">check_is_sorted_and_uniqued<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input <span style=\"color: #555555\">=<\/span> read_input(argc, argv);\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> sorted_and_uniqued <span style=\"color: #555555\">=<\/span> uniqued(sorted(decay_copy(input)));\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                                       ^^^^^^^^^^ &quot;explicit&quot; copy<\/span>\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (input <span style=\"color: #555555\">!=<\/span> sorted_and_uniqued) {\n        print_diff(input, sorted_and_uniqued);\n        exit(<span style=\"color: #FF6600\">1<\/span>);\n    }\n    exit(<span style=\"color: #FF6600\">0<\/span>);\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ This works, and in this case is optimal, but leaves something to be desired in generic cases.<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Let us try and see what happens if we try and refactor sort+unique into a generic<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ algorithm<\/span>\n\n<span style=\"color: #009999\">#endif<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Let&#39;s take our vector as a forwarding reference so we can reuse its memory if we own it<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ We need a concept for that<\/span>\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">inline<\/span> constexpr <span style=\"color: #007788; font-weight: bold\">bool<\/span> is_vector_v <span style=\"color: #555555\">=<\/span> <span style=\"color: #336666\">false<\/span>;\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T, <span style=\"color: #006699; font-weight: bold\">typename<\/span> A<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">inline<\/span> constexpr <span style=\"color: #007788; font-weight: bold\">bool<\/span> is_vector_v<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span>vector<span style=\"color: #555555\">&lt;<\/span>T, A<span style=\"color: #555555\">&gt;&gt;<\/span> <span style=\"color: #555555\">=<\/span> <span style=\"color: #336666\">true<\/span>;\n<span style=\"color: #006699; font-weight: bold\">template<\/span> <span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T<span style=\"color: #555555\">&gt;<\/span>\nconcept a_vector <span style=\"color: #555555\">=<\/span> is_vector_v<span style=\"color: #555555\">&lt;<\/span>std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">remove_cvref_t<\/span><span style=\"color: #555555\">&lt;<\/span>T<span style=\"color: #555555\">&gt;&gt;<\/span>;\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ we take this by forwarding reference; but now,<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ we make an additional move-construction if v is passed by rvalue reference<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">sorted_and_uniqued<\/span>(a_vector <span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;&amp;<\/span> v) {\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> uniqued(sorted(decay_copy(std<span style=\"color: #555555\">::<\/span>forward<span style=\"color: #555555\">&lt;<\/span>decltype(v)<span style=\"color: #555555\">&gt;<\/span>(v))));\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                    ^^^^^^^^^^ an extra move construction or the needed copy-construction<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ specifically, we move-construct decay_copy&#39;s return value.<\/span>\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ so, decay_copy is clearly not optimal. We need something that won&#39;t result<\/span>\n<span style=\"color: #0099FF; font-style: italic\">\/\/ in additional move-constructions and still accomplish our &quot;copies are explicit&quot; goal.<\/span>\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ enter: decay-copy in the language!<\/span>\n}\n\n<span style=\"color: #006699; font-weight: bold\">namespace<\/span> done_properly {\n<span style=\"color: #006699; font-weight: bold\">using<\/span> require_moves<span style=\"color: #555555\">::<\/span>sorted, require_moves<span style=\"color: #555555\">::<\/span>uniqued, require_moves<span style=\"color: #555555\">::<\/span>a_vector, require_moves<span style=\"color: #555555\">::<\/span>print_diff;\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ in regular user code, we can now use auto{} instead of decay-copy:<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">check_is_sorted_and_uniqued<\/span>(<span style=\"color: #007788; font-weight: bold\">int<\/span> argc, <span style=\"color: #007788; font-weight: bold\">char<\/span><span style=\"color: #555555\">**<\/span> argv) {\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> input <span style=\"color: #555555\">=<\/span> read_input(argc, argv);\n    <span style=\"color: #006699; font-weight: bold\">auto<\/span> sorted_and_uniqued <span style=\"color: #555555\">=<\/span> uniqued(sorted(<span style=\"color: #006699; font-weight: bold\">auto<\/span>(input)));\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                                       ^^^^^^^^^^^ explicit copy<\/span>\n    <span style=\"color: #006699; font-weight: bold\">if<\/span> (input <span style=\"color: #555555\">!=<\/span> sorted_and_uniqued) {\n        print_diff(input, sorted_and_uniqued);\n        exit(<span style=\"color: #FF6600\">1<\/span>);\n    }\n    exit(<span style=\"color: #FF6600\">0<\/span>);\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ in generic contexts<\/span>\n<span style=\"color: #006699; font-weight: bold\">auto<\/span> <span style=\"color: #CC00FF\">sorted_and_uniqued<\/span>(a_vector <span style=\"color: #006699; font-weight: bold\">auto<\/span><span style=\"color: #555555\">&amp;&amp;<\/span> v) {\n    <span style=\"color: #006699; font-weight: bold\">return<\/span> uniqued(sorted(<span style=\"color: #006699; font-weight: bold\">auto<\/span>(std<span style=\"color: #555555\">::<\/span>forward<span style=\"color: #555555\">&lt;<\/span>decltype(v)<span style=\"color: #555555\">&gt;<\/span>(v))));\n    <span style=\"color: #0099FF; font-style: italic\">\/\/                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<\/span>\n    <span style=\"color: #0099FF; font-style: italic\">\/\/ correct forwarded copy of an argument we took by forwarding reference<\/span>\n}\n}\n\n<span style=\"color: #0099FF; font-style: italic\">\/\/ Thanks for reading!<\/span>\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Here is more information about how to pass function parameters: <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-how-to-pass-function-parameters\/\" data-type=\"URL\" data-id=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-how-to-pass-function-parameters\/\">C++ Core Guidelines: The Rules for in, out, in-out, consume, and forward Function Parameter<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Multidimensional Subscript Operator<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Thanks to <code>std::mdspan<\/code>, C++23 supports multi-dimensional arrays. The C++23 core language also supports a multidimensional subscript operator to complete the feature.<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ multidimensionalSubscript.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;array&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n \n<span style=\"color: #006699; font-weight: bold\">template<\/span><span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T, std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> X, std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> Y<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Matrix {\n    std<span style=\"color: #555555\">::<\/span>array<span style=\"color: #555555\">&lt;<\/span>T, X <span style=\"color: #555555\">*<\/span> Y<span style=\"color: #555555\">&gt;<\/span> mat{};\n \n    T<span style=\"color: #555555\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span>[](std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> x, std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> y) {               <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> mat[y <span style=\"color: #555555\">*<\/span> X <span style=\"color: #555555\">+<\/span> x];\n    }\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\">&#39;\\n&#39;<\/span>;\n\n    Matrix<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>, <span style=\"color: #FF6600\">3<\/span>, <span style=\"color: #FF6600\">3<\/span><span style=\"color: #555555\">&gt;<\/span> mat;\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> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> j <span style=\"color: #555555\">:<\/span> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) mat[i, j] <span style=\"color: #555555\">=<\/span> (i <span style=\"color: #555555\">*<\/span> <span style=\"color: #FF6600\">3<\/span>) <span style=\"color: #555555\">+<\/span> j;       <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n    }\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> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> j <span style=\"color: #555555\">:<\/span> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> mat[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; &quot;<\/span>; <span style=\"color: #0099FF; font-style: italic\">\/\/ (3)<\/span>\n    }\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Line (1) defines the two-dimensional subscript operator for the class <code>Matrix<\/code>. Line (2) uses it to define the elements, and line (3) reads them.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the output of the program:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/multidimensionalSubscript.png\" alt=\"\" class=\"wp-image-7978\" style=\"width:278px;height:76px\" width=\"278\" height=\"76\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/multidimensionalSubscript.png 556w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2023\/08\/multidimensionalSubscript-300x81.png 300w\" sizes=\"auto, (max-width: 278px) 100vw, 278px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><code>static operator ()<\/code> and <code>operator []<\/code><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With C++23, the call <code>operator()<\/code> and the multi-dimensional subscript <code>operator []<\/code> can be static. You may ask, why? The answer is typical for C++: optimization<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Optimization<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The implicit <code>this <\/code>pointer must be passed around in an extra register if a member function cannot be inlined. Thanks to a static member function, you can spare the <code>this <\/code>pointer. Also, lambdas, which do not capture anything, can be <code>static <\/code>in C++23:<\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #006699; font-weight: bold\">auto<\/span> sum <span style=\"color: #555555\">=<\/span> [](<span style=\"color: #006699; font-weight: bold\">auto<\/span> a, <span style=\"color: #006699; font-weight: bold\">auto<\/span> b) <span style=\"color: #006699; font-weight: bold\">static<\/span> {<span style=\"color: #006699; font-weight: bold\">return<\/span> a <span style=\"color: #555555\">+<\/span> b;};\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">For consistency reasons, the multi-dimensional subscript<code> operator []<\/code> can also be static. <\/p>\n\n\n\n<!-- HTML generated using hilite.me --><div style=\"background: #f0f3f3; overflow:auto;width:auto;gray;border-width:.1em .1em .1em .8em\"><pre style=\"margin: 0; line-height: 125%\"><span style=\"color: #0099FF; font-style: italic\">\/\/ multidimensionalSubscriptStatic.cpp<\/span>\n\n<span style=\"color: #009999\">#include &lt;array&gt;<\/span>\n<span style=\"color: #009999\">#include &lt;iostream&gt;<\/span>\n \n<span style=\"color: #006699; font-weight: bold\">template<\/span><span style=\"color: #555555\">&lt;<\/span><span style=\"color: #006699; font-weight: bold\">typename<\/span> T, std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> X, std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> Y<span style=\"color: #555555\">&gt;<\/span>\n<span style=\"color: #006699; font-weight: bold\">struct<\/span> Matrix {\n\n    <span style=\"color: #006699; font-weight: bold\">static<\/span> <span style=\"color: #006699; font-weight: bold\">inline<\/span> std<span style=\"color: #555555\">::<\/span>array<span style=\"color: #555555\">&lt;<\/span>T, X <span style=\"color: #555555\">*<\/span> Y<span style=\"color: #555555\">&gt;<\/span> mat{};               <span style=\"color: #0099FF; font-style: italic\">\/\/ (2)<\/span>\n    \n    <span style=\"color: #006699; font-weight: bold\">static<\/span> T<span style=\"color: #555555\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold\">operator<\/span>[](std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> x, std<span style=\"color: #555555\">::<\/span><span style=\"color: #007788; font-weight: bold\">size_t<\/span> y) {    <span style=\"color: #0099FF; font-style: italic\">\/\/ (1)<\/span>\n        <span style=\"color: #006699; font-weight: bold\">return<\/span> mat[y <span style=\"color: #555555\">*<\/span> X <span style=\"color: #555555\">+<\/span> x];\n    }\n};\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\">&#39;\\n&#39;<\/span>;\n\n    Matrix<span style=\"color: #555555\">&lt;<\/span><span style=\"color: #007788; font-weight: bold\">int<\/span>, <span style=\"color: #FF6600\">3<\/span>, <span style=\"color: #FF6600\">3<\/span><span style=\"color: #555555\">&gt;<\/span> mat;\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> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> j <span style=\"color: #555555\">:<\/span> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) mat[i, j] <span style=\"color: #555555\">=<\/span> (i <span style=\"color: #555555\">*<\/span> <span style=\"color: #FF6600\">3<\/span>) <span style=\"color: #555555\">+<\/span> j;\n    }\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> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) {\n        <span style=\"color: #006699; font-weight: bold\">for<\/span> (<span style=\"color: #006699; font-weight: bold\">auto<\/span> j <span style=\"color: #555555\">:<\/span> {<span style=\"color: #FF6600\">0<\/span>, <span style=\"color: #FF6600\">1<\/span>, <span style=\"color: #FF6600\">2<\/span>}) std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> mat[i, j] <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&quot; &quot;<\/span>;  \n    }\n\n    std<span style=\"color: #555555\">::<\/span>cout <span style=\"color: #555555\">&lt;&lt;<\/span> <span style=\"color: #CC3300\">&#39;\\n&#39;<\/span>;\n\n}\n<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Now, the two-dimensional subscript <code>operator []<\/code> (line 1) and the <code>std::array mat <\/code>(line 2) are <code>static<\/code>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s next? <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">My next post will be a guest post by Victor Duvanenko. He provides exhaustive performance numbers about my favorite C++17 feature: the parallel STL algorithms.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>With the static multidimensional subscript and call operator, the C++23 core language has more to offer. auto(x) and auto{x} In my last post, &#8220;C++23: The Small Pearls in the Core Language&#8220;, I gave a concise explanation of auto(x) and auto{x}: The calls auto(x) and auto{x} cast x into a prvalue as if passing x as [&hellip;]<\/p>\n","protected":false},"author":21,"featured_media":7969,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[378],"tags":[436],"class_list":["post-7967","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-23","tag-auto"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7967","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=7967"}],"version-history":[{"count":22,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7967\/revisions"}],"predecessor-version":[{"id":8034,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/7967\/revisions\/8034"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/7969"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=7967"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=7967"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=7967"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}