{"id":2099,"date":"2022-02-03T17:23:10","date_gmt":"2022-02-03T16:23:10","guid":{"rendered":"http:\/\/www.nuonsoft.com\/blog\/?p=2099"},"modified":"2022-02-03T17:23:12","modified_gmt":"2022-02-03T16:23:12","slug":"c20-templated-lambda-expressions","status":"publish","type":"post","link":"https:\/\/www.nuonsoft.com\/blog\/2022\/02\/03\/c20-templated-lambda-expressions\/","title":{"rendered":"C++20: Templated Lambda Expressions"},"content":{"rendered":"\n<p>Templated lambda expressions allow you to get easy access to type information of generic lambda expression parameters. This also allows you to put constraints on the types of generic lambda expressions parameters. For example, the following generic lambda expression accepts two parameters, both defined with auto type deduction:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; quick-code: false; notranslate\" title=\"\">\n&#x5B;](const auto&amp; a, const auto&amp; b) { \/* ... *\/ }\n<\/pre><\/div>\n\n\n<p>Since both parameters are auto type deduced, the compiler is free to choose different types for both parameters. If you do not want this, you can use the following templated lambda expression:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; quick-code: false; notranslate\" title=\"\">\n&#x5B;]&lt;typename T&gt;(const T&amp; a, const T&amp; b) { \/* ... *\/ }\n<\/pre><\/div>\n\n\n<p>This can be combined with C++20 concepts to further constrain type <strong>T<\/strong>. For example, you can require that type <strong>T<\/strong> is an integral type as follows (needs <strong>&lt;concepts><\/strong>):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; quick-code: false; notranslate\" title=\"\">\n&#x5B;]&lt;std::integral T&gt;(const T&amp; a, const T&amp; b) { \/* ... *\/ }\n<\/pre><\/div>\n\n\n<p>Using a templated lambda expression, you have direct access to the type of a parameter. Hence, it&#8217;s easier to, for example, create a local variable in your lambda expression that has the same type as the type of one of the parameters. Without a templated lambda expression, you would have to involve <strong>decltype()<\/strong> and <strong>std::decay_t<\/strong> on generic lambda expression parameters to achieve the same thing.<\/p>\n\n\n\n<p>For example, suppose you have a lambda expression accepting a <strong>std::vector<\/strong> where the type of the elements can be anything. We can use a generic lambda expression for this. However, if in the body of the lambda, you want to know the exact type of the elements in the <strong>vector<\/strong>, you need to use <strong>decltype()<\/strong> and <strong>decay_t<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; quick-code: false; notranslate\" title=\"\">\n&#x5B;](const auto&amp; v) {\n\tusing V = std::decay_t&lt;decltype(v)&gt;; \/\/ vector&#039;s type\n\tusing T = typename V::value_type;    \/\/ vector element&#039;s type\n\tT temp;\n\t\/* ... *\/\n}\n<\/pre><\/div>\n\n\n<p>With a templated lambda expression you can make this much more concise and easier to understand:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; quick-code: false; notranslate\" title=\"\">\n&#x5B;]&lt;typename T&gt;(const std::vector&lt;T&gt;&amp; v) {\n\tT temp;\n\t\/* ... *\/\n}\n<\/pre><\/div>\n\n\n<p>My book,\u00a0<a rel=\"noreferrer noopener\" href=\"https:\/\/amzn.to\/2ZDHCCu\" target=\"_blank\">Professional C++, 5th Edition<\/a>, explains all new C++20 features, and much more.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Templated lambda expressions allow you to get easy access to type information of generic lambda expression parameters. This also allows you to put constraints on the types of generic lambda expressions parameters. For example, the following generic lambda expression accepts two parameters, both defined with auto type deduction: Since both parameters are auto type deduced, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[242],"class_list":["post-2099","post","type-post","status-publish","format-standard","hentry","category-c","tag-c20"],"_links":{"self":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/2099","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/comments?post=2099"}],"version-history":[{"count":6,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/2099\/revisions"}],"predecessor-version":[{"id":2106,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/posts\/2099\/revisions\/2106"}],"wp:attachment":[{"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/media?parent=2099"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/categories?post=2099"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nuonsoft.com\/blog\/wp-json\/wp\/v2\/tags?post=2099"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}