{"id":5802,"date":"2019-10-27T06:14:18","date_gmt":"2019-10-27T06:14:18","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-20-the-core-language\/"},"modified":"2023-06-26T09:58:50","modified_gmt":"2023-06-26T09:58:50","slug":"c-20-the-core-language","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-20-the-core-language\/","title":{"rendered":"C++ 20: The Core Language"},"content":{"rendered":"<p>My last post <a href=\"https:\/\/www.modernescpp.com\/index.php\/thebigfour\">C++20: The Big Four <\/a>started with an overview of concepts, ranges, coroutines, and modules. Of course, C++20 has more to offer. Today, let&#8217;s continue my overview of the core language.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5800\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/TimelineCpp20Core.png\" alt=\"TimelineCpp20Core\" width=\"650\" height=\"266\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/TimelineCpp20Core.png 1077w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/TimelineCpp20Core-300x123.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/TimelineCpp20Core-1024x419.png 1024w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/TimelineCpp20Core-768x314.png 768w\" sizes=\"auto, (max-width: 650px) 100vw, 650px\" \/><\/p>\n<h2><span class=\"ez-toc-section\" id=\"Core_Language\"><\/span>Core Language<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Looking at the image, you see the features I want to cover.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_three-way_Comparison_operator\"><\/span>The three-way Comparison operator &lt;=&gt;<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The three-way comparison operator <span style=\"font-family: courier new, courier;\">&lt;=&gt;<\/span> is often just called the spaceship operator. The spaceship operator determines whether A &lt; B, A = B, or A &gt; B for two values A and B.<\/p>\n<p>The compiler can auto-generate the three-way comparison operator. You have only to ask for it politely with <span style=\"font-family: courier new, courier;\">default.<\/span> In this case, you get all six comparison operators such as<span style=\"font-family: courier new, courier;\"> ==,&nbsp;!=, &lt;, &lt;=, &gt;, <\/span>and<span style=\"font-family: courier new, courier;\"> &gt;=. <\/span><\/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: #009999;\">#include &lt;compare&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> MyInt {\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> value;\r\n  MyInt(<span style=\"color: #007788; font-weight: bold;\">int<\/span> value)<span style=\"color: #555555;\">:<\/span> value{value} { }\r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span><span style=\"color: #555555;\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> MyInt<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">default<\/span>;\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The default operator &lt;=&gt; performs lexicographical comparison starting the base classes left to right and using the non-static members in declaration order. Here is a quite sophisticated example from the Microsoft blog: <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/simplify-your-code-with-rocket-science-c20s-spaceship-operator\/\">Simplify Your Code with Rocket Science: C++ 20&#8217;s Spaceship Operator.<\/a><span style=\"font-family: courier new, courier;\"><br \/><\/span><\/p>\n<p>&nbsp;<\/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;\">struct<\/span> Basics {\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> i;\r\n  <span style=\"color: #007788; font-weight: bold;\">char<\/span> c;\r\n  <span style=\"color: #007788; font-weight: bold;\">float<\/span> f;\r\n  <span style=\"color: #007788; font-weight: bold;\">double<\/span> d;\r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span><span style=\"color: #555555;\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Basics<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">default<\/span>;\r\n};\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Arrays {\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> ai[<span style=\"color: #ff6600;\">1<\/span>];\r\n  <span style=\"color: #007788; font-weight: bold;\">char<\/span> ac[<span style=\"color: #ff6600;\">2<\/span>];\r\n  <span style=\"color: #007788; font-weight: bold;\">float<\/span> af[<span style=\"color: #ff6600;\">3<\/span>];\r\n  <span style=\"color: #007788; font-weight: bold;\">double<\/span> ad[<span style=\"color: #ff6600;\">2<\/span>][<span style=\"color: #ff6600;\">2<\/span>];\r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span><span style=\"color: #555555;\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Arrays<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">default<\/span>;\r\n};\r\n \r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Bases <span style=\"color: #555555;\">:<\/span> Basics, Arrays {\r\n  <span style=\"color: #006699; font-weight: bold;\">auto<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span><span style=\"color: #555555;\">&lt;=&gt;<\/span>(<span style=\"color: #006699; font-weight: bold;\">const<\/span> Bases<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">default<\/span>;\r\n};\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n  constexpr Bases a <span style=\"color: #555555;\">=<\/span> { { <span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #cc3300;\">'c'<\/span>, <span style=\"color: #ff6600;\">1.f<\/span>, <span style=\"color: #ff6600;\">1.<\/span> },\r\n                        { { <span style=\"color: #ff6600;\">1<\/span> }, { <span style=\"color: #cc3300;\">'a'<\/span>, <span style=\"color: #cc3300;\">'b'<\/span> }, { <span style=\"color: #ff6600;\">1.f<\/span>, <span style=\"color: #ff6600;\">2.f<\/span>, <span style=\"color: #ff6600;\">3.f<\/span> }, { { <span style=\"color: #ff6600;\">1.<\/span>, <span style=\"color: #ff6600;\">2.<\/span> }, { <span style=\"color: #ff6600;\">3.<\/span>, <span style=\"color: #ff6600;\">4.<\/span> } } } };\r\n  constexpr Bases b <span style=\"color: #555555;\">=<\/span> { { <span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #cc3300;\">'c'<\/span>, <span style=\"color: #ff6600;\">1.f<\/span>, <span style=\"color: #ff6600;\">1.<\/span> },\r\n                        { { <span style=\"color: #ff6600;\">1<\/span> }, { <span style=\"color: #cc3300;\">'a'<\/span>, <span style=\"color: #cc3300;\">'b'<\/span> }, { <span style=\"color: #ff6600;\">1.f<\/span>, <span style=\"color: #ff6600;\">2.f<\/span>, <span style=\"color: #ff6600;\">3.f<\/span> }, { { <span style=\"color: #ff6600;\">1.<\/span>, <span style=\"color: #ff6600;\">2.<\/span> }, { <span style=\"color: #ff6600;\">3.<\/span>, <span style=\"color: #ff6600;\">4.<\/span> } } } };\r\n  static_assert(a <span style=\"color: #555555;\">==<\/span> b);\r\n  static_assert(<span style=\"color: #555555;\">!<\/span>(a <span style=\"color: #555555;\">!=<\/span> b));\r\n  static_assert(<span style=\"color: #555555;\">!<\/span>(a <span style=\"color: #555555;\">&lt;<\/span> b));\r\n  static_assert(a <span style=\"color: #555555;\">&lt;=<\/span> b);\r\n  static_assert(<span style=\"color: #555555;\">!<\/span>(a <span style=\"color: #555555;\">&gt;<\/span> b));\r\n  static_assert(a <span style=\"color: #555555;\">&gt;=<\/span> b);\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I assume the most complicated stuff in this code snippet is not the spaceship operator but the initialization of <span style=\"font-family: 'courier new', courier;\">Base<\/span> using aggregate initialization. Aggregate initialization essential means that you can directly initialize the members of class types (<span style=\"font-family: courier new, courier;\">class<\/span>, <span style=\"font-family: courier new, courier;\">struct,<\/span> or <span style=\"font-family: courier new, courier;\">union)<\/span> if all members are public. You can use, in this case, a braced-initialization list such as in the example. Okay, this was a simplification. Read the details here: <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/aggregate_initialization\">aggregate initialization<\/a>.&nbsp;<\/p>\n<\/p>\n<h3><span class=\"ez-toc-section\" id=\"String_Literals_as_Template_Parameters\"><\/span>String Literals as Template Parameters<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Before C++20, you could not use a string as a non-type template parameter. With C++20, you can use it. The idea is to use the standard defined <span style=\"font-family: courier new, courier;\">basic_fixed_string<\/span>, which has a <span style=\"font-family: courier new, courier;\">constexpr<\/span> constructor. The <span style=\"font-family: courier new, courier;\">constexpr<\/span> constructor enables it to instantiate the fixed string at compile-time.<\/p>\n<p>&nbsp;<\/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;std::basic_fixed_string<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Foo<\/span> {\r\n    <span style=\"color: #006699; font-weight: bold;\">static<\/span> constexpr <span style=\"color: #007788; font-weight: bold;\">char<\/span> <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">*<\/span> Name <span style=\"color: #555555;\">=<\/span> T;\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> hello() <span style=\"color: #006699; font-weight: bold;\">const<\/span>;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>() {\r\n    Foo<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #cc3300;\">\"Hello!\"<\/span><span style=\"color: #555555;\">&gt;<\/span> foo;\r\n    foo.hello();\r\n}\r\n<\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"constexpr_Virtual_Functions\"><\/span><span style=\"font-family: courier new, courier;\">constexpr<\/span> Virtual Functions<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Virtual functions can not be invoked in constant expressions because the dynamic type is unknown. This restriction will fall with C++20.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Designated_initializers\"><\/span>Designated initializers<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Let me first write about aggregate initialization. Here is a straightforward example.<\/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;\">\/\/ aggregateInitialisation.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Point2D{\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> y;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Point3D<\/span>{\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> y;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> z;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    Point2D point2D {<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>};\r\n    Point3D point3D {<span style=\"color: #ff6600;\">1<\/span>, <span style=\"color: #ff6600;\">2<\/span>, <span style=\"color: #ff6600;\">3<\/span>};\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"point2D: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point2D.x <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point2D.y <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"point3D: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point3D.x <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point3D.y <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point3D.z <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>I assume an explanation of the program is not necessary. Here is the output of the program:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5801\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/aggregateInitialisation.png\" alt=\"aggregateInitialisation\" width=\"400\" height=\"183\" style=\"display: block; margin-left: auto; margin-right: auto;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/aggregateInitialisation.png 500w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2019\/10\/aggregateInitialisation-300x137.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>Explicit is better than implicit. Let&#8217;s see what that means. The initialization in the program <span style=\"font-family: courier new, courier;\">aggregateInitialisation.cpp<\/span> is quite error-prone because you can swap the constructor arguments, and you will never notice. Here designated initializers from <a href=\"https:\/\/en.wikipedia.org\/wiki\/C99\">C99<\/a> kick in.<\/p>\n<p>&nbsp;<\/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;\">\/\/ designatedInitializer.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Point2D{\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> y;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Point3D<\/span>{\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> y;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> z;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    Point2D point2D {.x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>, .y <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2<\/span>};\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ Point2D point2d {.y = 2, .x = 1};         \/\/ (1) error<\/span>\r\n    Point3D point3D {.x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">1<\/span>, .y <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2<\/span>, .z <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">2<\/span>};   \r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ Point3D point3D {.x = 1, .z = 2}          \/\/ (2)  {1, 0, 2}<\/span>\r\n    \r\n\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"point2D: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point2D.x <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point2D.y <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"point3D: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point3D.x <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point3D.y <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> point3D.z <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n    \r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The arguments for the instances of <span style=\"font-family: courier new, courier;\">Point2d<\/span> and <span style=\"font-family: courier new, courier;\">Point3D<\/span> are explicitly named. The program&#8217;s output is identical to the output of the program <span style=\"font-family: courier new, courier;\">aggregateInitialisation.cpp<\/span>. The commented outlines (1) and (2) are pretty interesting. Line (1) would give an error because the order of the designator does not match their declaration order. The designator for y is missing inline (3). In this case, y would be initialized to 0 using braces-initialization-list <span style=\"font-family: courier new, courier;\">{1, 0, 3}.<\/span><\/p>\n<h3><span class=\"ez-toc-section\" id=\"Various_Lambda_Improvements\"><\/span>Various Lambda Improvements<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Lambas will have many improvements in C++20.<\/p>\n<p>If you want more details, go to <a href=\"https:\/\/www.bfilipek.com\/2019\/02\/lambdas-story-part1.html\">Bartek&#8217;s post<\/a> about lambda improvements in C++17 and C++20 or wait for my detailed posts. Anyway, here are two exciting changes we will get.<\/p>\n<ul>\n<li>\n<p><strong>Allow [=, this] as lambda capture and deprecate implicit capture of this via [=]<\/strong><\/p>\n<\/li>\n<\/ul>\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;\">struct<\/span> Lambda {\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> foo() {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> [<span style=\"color: #555555;\">=<\/span>] { std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> s <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl; };\r\n    }\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>string s;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> LambdaCpp20 {\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> foo() {\r\n        <span style=\"color: #006699; font-weight: bold;\">return<\/span> [<span style=\"color: #555555;\">=<\/span>, <span style=\"color: #006699; font-weight: bold;\">this<\/span>] { std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> s <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl; };\r\n    }\r\n\r\n    std<span style=\"color: #555555;\">::<\/span>string s;\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The implicit<span style=\"font-family: courier new, courier;\"> [=]<\/span> capture by copy inside the struct Lambda causes in C++20 a deprecation warning. You don&#8217;t get with C++20 a deprecation warning when you capture this explicitly by copying<span style=\"font-family: courier new, courier;\"> [=, this<\/span>].<\/p>\n<ul>\n<li>\n<p><strong>Template lambdas<br \/><\/strong><\/p>\n<\/li>\n<\/ul>\n<p>Your first impression, like mine may be: Why do we need template lambdas? When you write a generic lambda with C++14 <span style=\"font-family: courier new, courier;\">[](auto x){ return x; }<\/span>, the compiler automatically generates a class with a templatized call operator:<\/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;\">typename<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\r\nT <span style=\"color: #006699; font-weight: bold;\">operator<\/span>(T x) <span style=\"color: #006699; font-weight: bold;\">const<\/span> {\r\n    <span style=\"color: #006699; font-weight: bold;\">return<\/span> x;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Sometimes, you want to define a lambda that works only for a specific type, such as a <span style=\"font-family: courier new, courier;\">std::vector. <\/span>Now, template lambdas have come to our rescue. Instead of a type parameter, you can also use a concept:<\/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;\">auto<\/span> foo <span style=\"color: #555555;\">=<\/span> []<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T<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> <span style=\"color: #006699; font-weight: bold;\">const<\/span><span style=\"color: #555555;\">&amp;<\/span> vec) { \r\n        <span style=\"color: #0099ff; font-style: italic;\">\/\/ do vector specific stuff<\/span>\r\n    };\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"New_Attributes_likely_and_unlikely\"><\/span>New Attributes: <span style=\"font-family: courier new, courier;\">[[likely]] <\/span>and <span style=\"font-family: courier new, courier;\">[[unlikely]]<\/span><span style=\"font-family: courier new, courier;\"><\/span><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>With C++20, we get new attributes<span style=\"font-family: courier new, courier;\"> [[likely]<\/span>] and<span style=\"font-family: courier new, courier;\"> [[unlikely]].<\/span>&nbsp;Both attributes allow it to give the optimizer a hint of whether the path of execution is more or less likely.<\/p>\n<p>&nbsp;<\/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;\">for<\/span>(<span style=\"color: #007788; font-weight: bold;\">size_t<\/span> i<span style=\"color: #555555;\">=<\/span><span style=\"color: #ff6600;\">0<\/span>; i <span style=\"color: #555555;\">&lt;<\/span> v.size(); <span style=\"color: #555555;\">++<\/span>i){\r\n    <span style=\"color: #006699; font-weight: bold;\">if<\/span> (v[i] <span style=\"color: #555555;\">&lt;<\/span> <span style=\"color: #ff6600;\">0<\/span>) [[likely]] sum <span style=\"color: #555555;\">-=<\/span> sqrt(<span style=\"color: #555555;\">-<\/span>v[i]);\r\n    <span style=\"color: #006699; font-weight: bold;\">else<\/span> sum <span style=\"color: #555555;\">+=<\/span> sqrt(v[i]);\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"consteval_and_constinit_Specifier\"><\/span><span style=\"font-family: courier new, courier;\">consteval<\/span> and <span style=\"font-family: courier new, courier;\">constinit<\/span> Specifier<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The new specifier <span style=\"font-family: courier new, courier;\">consteval<\/span> creates an immediate function. For an immediate function, every call to the function must produce a compile-time constant expression. An immediate function is implicit a <span style=\"font-family: courier new, courier;\">constexpr<\/span> function.<\/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%;\">consteval <span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">sqr<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> n) {\r\n  <span style=\"color: #006699; font-weight: bold;\">return<\/span> n<span style=\"color: #555555;\">*<\/span>n;\r\n}\r\nconstexpr <span style=\"color: #007788; font-weight: bold;\">int<\/span> r <span style=\"color: #555555;\">=<\/span> sqr(<span style=\"color: #ff6600;\">100<\/span>);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK<\/span>\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">100<\/span>;\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> r2 <span style=\"color: #555555;\">=<\/span> sqr(x);             <span style=\"color: #0099ff; font-style: italic;\">\/\/ Error<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The final assignment gives an error because <span style=\"font-family: courier new, courier;\">x<\/span> is not a constant expression and, therefore, <span style=\"font-family: courier new, courier;\">sqr(x)<\/span> can not&nbsp; be performed at compile-time<\/p>\n<p><span style=\"font-family: courier new, courier;\">constinit<\/span> ensures that the variable with static storage duration is initialized at compile-time. Static storage duration means that the object is allocated when the program begins and deallocated when the program ends. Objects declared at namespace scope (global objects), declared as <span style=\"font-family: courier new, courier;\">static<\/span> or <span style=\"font-family: courier new, courier;\">extern<\/span> have static storage duration.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"std_source_location\"><\/span><span style=\"font-family: courier new, courier;\">std::source_location<\/span><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>C++11 has two macros for <span style=\"font-family: courier new, courier;\">__LINE__<\/span> and <span style=\"font-family: courier new, courier;\">__FILE__<\/span> to get the information when the macros are used. With C++20, the class <span style=\"font-family: courier new, courier;\">source_location<\/span> gives you the file name, the line number, the column number, and the function name of the source code. The short example from <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/utility\/source_location\">cppreference.com<\/a> shows the first usage:<\/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: #009999;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string_view&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;source_location&gt;<\/span>\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">log<\/span>(std<span style=\"color: #555555;\">::<\/span>string_view message,\r\n         <span style=\"color: #006699; font-weight: bold;\">const<\/span> std<span style=\"color: #555555;\">::<\/span>source_location<span style=\"color: #555555;\">&amp;<\/span> location <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>source_location<span style=\"color: #555555;\">::<\/span>current())\r\n{\r\n    std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"info:\"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> location.file_name() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\":\"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> location.line() <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\" \"<\/span>\r\n              <span style=\"color: #555555;\">&lt;&lt;<\/span> message <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;\r\n}\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>()\r\n{\r\n    log(<span style=\"color: #cc3300;\">\"Hello world!\"<\/span>);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ info:main.cpp:15 Hello world!<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"Whats_next\"><\/span>What&#8217;s next?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>This post was the first overview of the more minor features of the core language. The <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-20-the-library\">next post<\/a> continues my story with the library features in C++20.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My last post C++20: The Big Four started with an overview of concepts, ranges, coroutines, and modules. Of course, C++20 has more to offer. Today, let&#8217;s continue my overview of the core language.<\/p>\n","protected":false},"author":21,"featured_media":5800,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[375],"tags":[428,459,463],"class_list":["post-5802","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-20","tag-constexpr","tag-lambdas","tag-string"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5802","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=5802"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5802\/revisions"}],"predecessor-version":[{"id":6768,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5802\/revisions\/6768"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5800"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5802"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5802"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5802"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}