{"id":685,"date":"2022-10-11T09:10:37","date_gmt":"2022-10-11T09:10:37","guid":{"rendered":"https:\/\/tbekk.com\/devstream\/?p=685"},"modified":"2022-10-11T09:10:37","modified_gmt":"2022-10-11T09:10:37","slug":"all-major-c17-features-you-should-know","status":"publish","type":"post","link":"https:\/\/tbekk.com\/devstream\/blog\/2022\/10\/11\/all-major-c17-features-you-should-know\/","title":{"rendered":"All Major C++17 Features You Should Know"},"content":{"rendered":"\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<ul class=\"wp-block-list\"><li><em><strong>Link: <\/strong><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/\">https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/<\/a><\/em><\/li><li><strong><em>Publication data<\/em><\/strong><em><strong>: <\/strong>10th October 2022<\/em><\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator is-style-wide\"\/>\n\n\n\n<p>The ISO Committee accepted and published the C++17 Standard in December 2017. In this mega-long article, I\u2019ve built (with your help!) a list of\u00a0<strong>all major features<\/strong>\u00a0of the new standard.<\/p>\n\n\n\n<p>Please have a look and see what we get!<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#language-features\">Language Features<\/a><ul><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#new-auto-rules-for-direct-list-initialization\">New auto rules for direct-list-initialization<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#staticassert-with-no-message\">static_assert with no message<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#typename-in-a-template-template-parameter\">typename in a template template parameter<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#removing-trigraphs\">Removing trigraphs<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#nested-namespace-definition\">Nested namespace definition<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#attributes-for-namespaces-and-enumerators\">Attributes for namespaces and enumerators<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#u8-character-literals\">u8 character literals<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#allow-constant-evaluation-for-all-non-type-template-arguments\">Allow constant evaluation for all non-type template arguments<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#fold-expressions\">Fold Expressions<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#unary-fold-expressions-and-empty-parameter-packs\">Unary fold expressions and empty parameter packs<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#remove-deprecated-use-of-the-register-keyword\">Remove Deprecated Use of the register Keyword<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#remove-deprecated-operatorbool\">Remove Deprecated operator++(bool)<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#removing-deprecated-exception-specifications-from-c17\">Removing Deprecated Exception Specifications from C++17<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#make-exception-specifications-part-of-the-type-system\">Make exception specifications part of the type system<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#aggregate-initialization-of-classes-with-base-classes\">Aggregate initialization of classes with base classes<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#lambda-capture-of-this\">Lambda capture of *this<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#using-attribute-namespaces-without-repetition\">Using attribute namespaces without repetition<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#dynamic-memory-allocation-for-over-aligned-data\">Dynamic memory allocation for over-aligned data<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#hasinclude-in-preprocessor-conditionals\">__has_include in preprocessor conditionals<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#template-argument-deduction-for-class-templates\">Template argument deduction for class templates<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#non-type-template-parameters-with-auto-type\">Non-type template parameters with auto type<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#guaranteed-copy-elision\">Guaranteed copy elision<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#new-specification-for-inheriting-constructors-dr1941-et-al\">New specification for inheriting constructors (DR1941 et al)<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#direct-list-initialization-of-enumerations\">Direct-list-initialization of enumerations<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stricter-expression-evaluation-order\">Stricter expression evaluation order<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#constexpr-lambda-expressions\">constexpr lambda expressions<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#different-begin-and-end-types-in-range-based-for\">Different begin and end types in range-based for<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#fallthrough-attribute\">[[fallthrough]] attribute<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#nodiscard-attribute\">[[nodiscard]] attribute<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#maybeunused-attribute\">[[maybe_unused]] attribute<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#ignore-unknown-attributes\">Ignore unknown attributes<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#pack-expansions-in-using-declarations\">Pack expansions in using-declarations<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#structured-binding-declarations\">Structured Binding Declarations<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#hexadecimal-floating-point-literals\">Hexadecimal floating-point literals<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#init-statements-for-if-and-switch\">init-statements for if and switch<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#inline-variables\">Inline variables<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#dr-matching-of-template-template-arguments-excludes-compatible-templates\">DR: Matching of template template-arguments excludes compatible templates<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stduncaughtexceptions\">std::uncaught_exceptions()<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#constexpr-if-statements\">constexpr if-statements<\/a><ul><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#sfinae\">SFINAE<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#tag-dispatching\">Tag dispatching<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#if-constexpr\">if constexpr<\/a><\/li><\/ul><\/li><\/ul><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#library-features\">Library Features<\/a><ul><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-the-library-fundamentals-1-ts-most-parts\">Merged: The Library Fundamentals 1 TS (most parts)<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#removal-of-some-deprecated-types-and-functions-including-stdautoptr-stdrandomshuffle-and-old-function-adaptors\">Removal of some deprecated types and functions, including std::auto_ptr, std::random_shuffle, and old function adaptors<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-the-parallelism-ts-aka-parallel-stl\">Merged: The Parallelism TS, a.k.a. \u201cParallel STL.\u201d,<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-file-system-ts\">Merged: File System TS,<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-the-mathematical-special-functions-is\">Merged: The Mathematical Special Functions IS,<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#improving-stdpair-and-stdtuple\">Improving std::pair and std::tuple<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stdsharedmutex-untimed\">std::shared_mutex (untimed)<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#variant\">Variant<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#splicing-maps-and-sets\">Splicing Maps and Sets<\/a><\/li><\/ul><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#contributors\">Contributors<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#summary\">Summary<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"intro\">Intro&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#intro\">&nbsp;<\/a>&nbsp;<\/h2>\n\n\n\n<p><strong>Updated<\/strong>: This post was updated on 10th October 2022.<\/p>\n\n\n\n<p>If you have code examples, better explanations or any ideas, let me know! I am happy to update the current post so that it has some real value for others.<\/p>\n\n\n\n<p>The plan is to have a list of features with some basic explanation, little example (if possible) and some additional resources, plus a note about availability in compilers. Probably, most of the features might require separate articles or even whole chapters in books, so the list here will be only a jump start.<\/p>\n\n\n\n<p><strong>See this<\/strong>&nbsp;GitHub repo:&nbsp;<a href=\"https:\/\/github.com\/fenbf\/cpp17features\">github\/fenbf\/cpp17features<\/a>. Add a pull request to update the content.<\/p>\n\n\n\n<p>The feature list comes from the following resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/stackoverflow.com\/questions\/38060436\/what-are-the-new-features-in-c17\">SO: What are the new features in C++17?<\/a><\/li><li><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/compiler_support\">cppreference.com\/C++ compiler support<\/a>.<\/li><li><a href=\"https:\/\/github.com\/AnthonyCalandra\/modern-cpp-features\">AnthonyCalandra\/modern-cpp-features cheat sheet<\/a>&nbsp;&#8211; unfortunately it doesn\u2019t include all the features of C++17.<\/li><li>plus other findings and mentions<\/li><\/ul>\n\n\n\n<p>And one of the most important resource:&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2017\/n4659.pdf\">N4659, 2017-03-21,&nbsp;<strong>Draft, Standard for Programming Language C++<\/strong><\/a>&nbsp;&#8211; from&nbsp;<a href=\"https:\/\/isocpp.org\/\">isocpp.org<\/a>.<\/p>\n\n\n\n<p>Plus, there\u2019s an official list of changes:&nbsp;<a href=\"https:\/\/isocpp.org\/files\/papers\/p0636r0.html\">P0636r0: Changes between C++14 and C++17 DIS<\/a><\/p>\n\n\n\n<p>Also, you can grab my list of concise descriptions of all of the C++17 &#8211; It\u2019s a one-page reference card:<\/p>\n\n\n\n<p><a href=\"http:\/\/eepurl.com\/cyycFz\">Download a free copy of my C++17 Cheat Sheet!<\/a><\/p>\n\n\n\n<p>I also have a more detailed series:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/05\/cpp17-details-fixes-deprecation.html\">Fixes and deprecation<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/06\/cpp17-details-clarifications.html\">Language clarification<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/06\/cpp17-details-templates.htm\">Templates<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/07\/cpp17-in-details-attributes.html\">Attributes<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/07\/cpp17-details-simplifications.html\">Simplification<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/08\/cpp17-details-filesystem.html\">Library changes &#8211; Filesystem<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/08\/cpp17-details-parallel.html\">Library changes &#8211; Parallel STL<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/09\/cpp17-details-utils.html\">Library changes &#8211; Utils<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/09\/c17-in-detail-summary-bonus.html\">Wrap up, Bonus<\/a>&nbsp;&#8211; with a free ebook! \ud83d\ude42<\/li><\/ol>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/leanpub.com\/cpp17indetail\"><img decoding=\"async\" src=\"https:\/\/www.cppstories.com\/2017\/images\/2017-01-09-c-17-features-cpp17indetail.png\" alt=\"\"\/><\/a><\/figure>\n\n\n\n<p>Resources about C++17 STL:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/leanpub.com\/cpp17\"><strong>C++17 In Detail<\/strong><\/a>&nbsp;by Bartek!<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"language-features\">Language Features&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#language-features\">&nbsp;<\/a>&nbsp;<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"new-auto-rules-for-direct-list-initialization\">New auto rules for direct-list-initialization&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#new-auto-rules-for-direct-list-initialization\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n3922.html\">N3922<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 5.0<\/th><th>Clang: 3.8<\/th><th>MSVC: 14.0<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Fixes some cases with auto type deduction. The full background can be found in&nbsp;<a href=\"http:\/\/open-std.org\/JTC1\/SC22\/WG21\/docs\/papers\/2013\/n3681.html\">Auto and braced-init-lists<\/a>, by Ville Voutilainen.<\/p>\n\n\n\n<p>It fixes the problem of deducing&nbsp;<code>std::initializer_list<\/code>&nbsp;like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>auto<\/strong> x = foo(); <em>\/\/ copy-initialization\n<\/em><em><\/em><strong>auto<\/strong> x{foo}; <em>\/\/ direct-initialization, initializes an initializer_list\n<\/em><em><\/em><strong>int<\/strong> x = foo(); <em>\/\/ copy-initialization\n<\/em><em><\/em><strong>int<\/strong> x{foo}; <em>\/\/ direct-initialization\n<\/em><\/code><\/pre>\n\n\n\n<p>And for the direct initialization, new rules are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>For a braced-init-list with only a single element, auto deduction will deduce from that entry;<\/li><li>For a braced-init-list with more than one element, auto deduction will be ill-formed.<\/li><\/ul>\n\n\n\n<p>Basically,&nbsp;<code>auto x { 1 };<\/code>&nbsp;will be now deduced as&nbsp;<code>int<\/code>, but before it was an initializer list.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"static_assert-with-no-message\"><code>static_assert<\/code>&nbsp;with no message&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#static_assert-with-no-message\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n3928.pdf\">N3928<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 2.5<\/th><th>MSVC: 15.0 preview 5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Self-explanatory. It allows just to have the condition without passing the message, version with the message will also be available. It will be compatible with other asserts like&nbsp;<code>BOOST_STATIC_ASSERT<\/code>&nbsp;(that didn\u2019t take any message from the start).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"typename-in-a-template-template-parameter\"><code>typename<\/code>&nbsp;in a&nbsp;<code>template template<\/code>&nbsp;parameter&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#typename-in-a-template-template-parameter\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4051.html\">N4051<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 5.0<\/th><th>Clang: 3.5<\/th><th>MSVC: 14.0<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Allows you to use&nbsp;<code>typename<\/code>&nbsp;instead of&nbsp;<code>class<\/code>&nbsp;when declaring a template template parameter. Normal type parameters can use them interchangeably, but template template parameters were restricted to&nbsp;<code>class<\/code>, so this change unifies these forms somewhat.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>template<\/strong> &lt;<strong>typename<\/strong>...&gt; <strong>typename<\/strong> Container&gt;\n<em>\/\/            used to be invalid ^^^^^^^^\n<\/em><em><\/em><strong>struct<\/strong> <strong>foo<\/strong>;\n\nfoo&lt;std::vector&gt; my_foo;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"removing-trigraphs\">Removing trigraphs&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#removing-trigraphs\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4086.html\">N4086<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 5.1<\/th><th>Clang: 3.5<\/th><th>MSVC: Yes<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Removes&nbsp;<code>??=<\/code>,&nbsp;<code>??(<\/code>,&nbsp;<code>??&gt;<\/code>, \u2026<\/p>\n\n\n\n<p>Makes the implementation a bit simpler, see&nbsp;<a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/bt0y4awe.aspx\">MSDN Trigraphs<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"nested-namespace-definition\">Nested namespace definition&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#nested-namespace-definition\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4230.html\">N4230<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.6<\/th><th>MSVC: 14.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Allows to write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>namespace<\/strong> A::B::C {\n   <em>\/\/ ...\n<\/em><em><\/em>}\n<\/code><\/pre>\n\n\n\n<p>Rather than:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>namespace<\/strong> A {\n    <strong>namespace<\/strong> B {\n        <strong>namespace<\/strong> C {\n            <em>\/\/ ...\n<\/em><em><\/em>        }\n    }\n}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"attributes-for-namespaces-and-enumerators\">Attributes for namespaces and enumerators&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#attributes-for-namespaces-and-enumerators\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4266.html\">N4266<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 4.9 (namespaces)\/ 6 (enums)<\/th><th>Clang: 3.4<\/th><th>MSVC: 14.0<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Permits attributes on enumerators and namespaces. More details in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4196.html\">N4196<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>enum<\/strong> <strong>E<\/strong> {\n  foobar = 0,\n  foobat &#91;&#91;deprecated]] = foobar\n};\n\nE e = foobat; <em>\/\/ Emits warning\n<\/em><em><\/em>\n<strong>namespace<\/strong> &#91;&#91;deprecated]] old_stuff{\n    <strong>void<\/strong> legacy();\n}\n\nold_stuff::legacy(); <em>\/\/ Emits warning\n<\/em><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"u8-character-literals\"><code>u8<\/code>&nbsp;character literals&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#u8-character-literals\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4267.html\">N4267<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.6<\/th><th>MSVC: 14.0<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>UTF-8 character literal, e.g.&nbsp;<code>u8'a'<\/code>. Such literal has type&nbsp;<code>char<\/code>&nbsp;and the value equal to ISO 10646 code point value of c-char, provided that the code point value is representable with a single UTF-8 code unit. If c-char is not in Basic Latin or C0 Controls Unicode block, the program is ill-formed.<\/p><\/blockquote>\n\n\n\n<p>The compiler will report errors if a character cannot fit inside&nbsp;<code>u8<\/code>&nbsp;ASCII range.<\/p>\n\n\n\n<p>Reference:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/character_literal\">cppreference.com\/character literal<\/a><\/li><li><a href=\"http:\/\/stackoverflow.com\/questions\/31970111\/what-is-the-point-of-the-utf-8-character-literals-proposed-for-c17\">SO: What is the point of the UTF-8 character literals proposed for C++17?<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"allow-constant-evaluation-for-all-non-type-template-arguments\">Allow constant evaluation for all non-type template arguments&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#allow-constant-evaluation-for-all-non-type-template-arguments\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4268.html\">N4268<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.6<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Remove syntactic restrictions for pointers, references, and pointers to members that appear as non-type template parameters:<\/p>\n\n\n\n<p>For instance:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong>&lt;<strong>int<\/strong> *p&gt; <strong>struct<\/strong> <strong>A<\/strong> {};\n<strong>int<\/strong> n;\nA&lt;&amp;n&gt; a; <em>\/\/ ok\n<\/em><em><\/em>\n<strong>constexpr<\/strong> <strong>int<\/strong> *p() { <strong>return<\/strong> &amp;n; }\nA&lt;p()&gt; b; <em>\/\/ error before C++17\n<\/em><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fold-expressions\">Fold Expressions&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#fold-expressions\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4295.html\">N4295<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.6<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>More background here in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0036r0.pdf\">P0036<\/a><\/p>\n\n\n\n<p>Allows writing compact code with variadic templates without using explicit recursion.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong>&lt;<strong>typename<\/strong>... Args&gt;\n<strong>auto<\/strong> SumWithOne(Args... args){\n    <strong>return<\/strong> (1 + ... + args);\n}\n<\/code><\/pre>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/06\/cpp17-details-templates.html#fold-expressions\">Bartek\u2019s coding blog: C++17 in details: Templates<\/a><\/li><li><a href=\"http:\/\/cpptruths.blogspot.com\/2017\/01\/folding-monadic-functions.html\">C++ Truths: Folding Monadic Functions<\/a><\/li><li><a href=\"https:\/\/tartanllama.github.io\/c++\/2016\/11\/10\/exploding-tuples-fold-expressions\/\">Simon Brand: Exploding tuples with fold expressions<\/a><\/li><li><a href=\"http:\/\/baptiste-wicht.com\/posts\/2015\/05\/cpp17-fold-expressions.html\">Baptiste Wicht: C++17 Fold Expressions<\/a><\/li><li><a href=\"http:\/\/www.modernescpp.com\/index.php\/fold-expressions\">Fold Expressions &#8211; ModernesCpp.com<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"unary-fold-expressions-and-empty-parameter-packs\">Unary fold expressions and empty parameter packs&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#unary-fold-expressions-and-empty-parameter-packs\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0036r0\">P0036R0<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.9<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>If the parameter pack is empty then the value of the fold is:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Operator<\/th><th>Value<\/th><\/tr><\/thead><tbody><tr><td>&amp;&amp;<\/td><td>true<\/td><\/tr><tr><td>||<\/td><td>false<\/td><\/tr><tr><td>,<\/td><td>void()<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>For any operator not listed above, an unary fold expression with an empty parameter pack is ill-formed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"remove-deprecated-use-of-the-register-keyword\">Remove Deprecated Use of the&nbsp;<code>register<\/code>&nbsp;Keyword&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#remove-deprecated-use-of-the-register-keyword\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0001r1.html\">P0001R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.8<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>The&nbsp;<code>register<\/code>&nbsp;keyword was deprecated in the 2011 C++ standard. C++17 tries to clear the standard, so the keyword is now removed. This keyword is reserved now and might be repurposed in future revisions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"remove-deprecated-operatorbool\">Remove Deprecated&nbsp;<code>operator++(bool)<\/code>&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#remove-deprecated-operatorbool\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0002r1.html\">P0002R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.8<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>The&nbsp;<code>++operator<\/code>&nbsp;for&nbsp;<code>bool<\/code>&nbsp;was deprecated in the original 1998 C++ standard, and it is past time to remove it formally.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"removing-deprecated-exception-specifications-from-c17\">Removing Deprecated Exception Specifications from C++17&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#removing-deprecated-exception-specifications-from-c17\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0003r5\">P0003R5<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.0<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Dynamic exception specifications were deprecated in C++11. This paper formally proposes removing the feature from C++17, while retaining the (still) deprecated&nbsp;<code>throw()<\/code>&nbsp;specification strictly as an alias for&nbsp;<code>noexcept(true)<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"make-exception-specifications-part-of-the-type-system\">Make exception specifications part of the type system&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#make-exception-specifications-part-of-the-type-system\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0012r1\">P0012R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Previously exception specifications for a function didn\u2019t belong to the type of the function, but it will be part of it.<\/p>\n\n\n\n<p>We\u2019ll get an error in the case:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> (*p)();\n<strong>void<\/strong> (**pp)() <strong>noexcept<\/strong> = &amp;p;   <em>\/\/ error: cannot convert to pointer to noexcept function\n<\/em><em><\/em>\n<strong>struct<\/strong> <strong>S<\/strong> { <strong>typedef<\/strong> void (*p)(); <strong>operator<\/strong> p(); };\n<strong>void<\/strong> (*q)() <strong>noexcept<\/strong> = S();   <em>\/\/ error: cannot convert to pointer to noexcept function\n<\/em><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"aggregate-initialization-of-classes-with-base-classes\">Aggregate initialization of classes with base classes&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#aggregate-initialization-of-classes-with-base-classes\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0017r1.html\">P0017R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: VS 2017 15.7<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>If a class was derived from some other type you couldn\u2019t use aggregate initialization. But now the restriction is removed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>struct<\/strong> <strong>base<\/strong> { <strong>int<\/strong> a1, a2; };\n<strong>struct<\/strong> <strong>derived<\/strong> : base { <strong>int<\/strong> b1; };\n\nderived d1{{1, 2}, 3};      <em>\/\/ full explicit initialization\n<\/em><em><\/em>derived d1{{}, 1};          <em>\/\/ the base is value initialized\n<\/em><\/code><\/pre>\n\n\n\n<p>To sum up: from the standard:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>An aggregate is an array or a class with:<br>* no user-provided constructors (including those inherited from a base class),<br>* no private or protected non-static data members (Clause 11),<br>* no base classes (Clause 10) and \/\/ removed now!<br>* no virtual functions (10.3), and<br>* no virtual, private or protected base classes (10.1).<\/p><\/blockquote>\n\n\n\n<p>See more in&nbsp;<a href=\"https:\/\/www.cppstories.com\/2022\/five-topics-data-members-cpp20\/#1-changing-status-of-aggregates\">Five tricky topics for data members in C++20 &#8211; C++ Stories<\/a>&nbsp;&#8211; \u201cChanging status of aggregates\u201d<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"lambda-capture-of-this\">Lambda capture of&nbsp;<code>*this<\/code>&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#lambda-capture-of-this\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0018r3.html\">P0018R3<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p><code>this<\/code>&nbsp;pointer is implicitly captured by lambdas inside member functions (if you use a default capture, like&nbsp;<code>[&amp;]<\/code>&nbsp;or&nbsp;<code>[=]<\/code>). Member variables are always accessed by this pointer.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>struct<\/strong> <strong>S<\/strong> {\n   <strong>int<\/strong> x ;\n   <strong>void<\/strong> f() {\n      <em>\/\/ The following lambda captures are currently identical\n<\/em><em><\/em>      <strong>auto<\/strong> a = &#91;&amp;]() { x = 42 ; } <em>\/\/ OK: transformed to (*this).x\n<\/em><em><\/em>      <strong>auto<\/strong> b = &#91;=]() { x = 43 ; } <em>\/\/ OK: transformed to (*this).x\n<\/em><em><\/em>      a();\n      assert( x == 42 );\n      b();\n      assert( x == 43 );\n   }\n};\n<\/code><\/pre>\n\n\n\n<p>Now you can use&nbsp;<code>*this<\/code>&nbsp;when declaring a lambda, for example&nbsp;<code>auto b = [=, *this]() { x = 43 ; }<\/code>. That way&nbsp;<code>this<\/code>&nbsp;is captured by value. Note that the form&nbsp;<code>[&amp;,this]<\/code>&nbsp;is redundant but accepted for compatibility with ISO C++14.<\/p>\n\n\n\n<p>Capturing by value might be especially important for async invocation, paraller processing.<\/p>\n\n\n\n<p>See more at&nbsp;<a href=\"https:\/\/www.cppstories.com\/2020\/05\/lambdas-async.html\/#capturing-this\">C++ Lambdas, Threads, std::async and Parallel Algorithms &#8211; C++ Stories<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"using-attribute-namespaces-without-repetition\">Using attribute namespaces without repetition&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#using-attribute-namespaces-without-repetition\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0028r4\">P0028R4<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Other name for this feature was \u201cUsing non-standard attributes\u201d in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0028r3.html\">P0028R3<\/a>&nbsp;and&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0028r2.pdf\">PDF: P0028R2<\/a>&nbsp;(rationale, examples).<\/p>\n\n\n\n<p>Simplifies the case where you want to use multiple attributes, like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> f() {\n    &#91;&#91;rpr::kernel, rpr::target(cpu,gpu)]] <em>\/\/ repetition\n<\/em><em><\/em>    <strong>do<\/strong>-task();\n}\n<\/code><\/pre>\n\n\n\n<p>Proposed change:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> f() {\n    &#91;&#91;using rpr: kernel, target(cpu,gpu)]]\n    <strong>do<\/strong>-task();\n}\n<\/code><\/pre>\n\n\n\n<p>That simplification might help when building tools that automatically translate annotated such code into a different programming models.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"dynamic-memory-allocation-for-over-aligned-data\">Dynamic memory allocation for over-aligned data&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#dynamic-memory-allocation-for-over-aligned-data\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0035r4\">P0035R4<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>In the following example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>class<\/strong> alignas(16) float4 {\n    <strong>float<\/strong> f&#91;4];\n};\nfloat4 *p = <strong>new<\/strong> float4&#91;1000];\n<\/code><\/pre>\n\n\n\n<p>C++11\/14 did not specify any mechanism by which over-aligned data can be dynamically allocated correctly (i.e. respecting the alignment of the data). In the example above, not only is an implementation of C++ not required to allocate properly-aligned memory for the array, for practical purposes it is very nearly required to do the allocation incorrectly.<\/p>\n\n\n\n<p>C++17 fixes that hole by introducing additional memory allocation functions that use align parameter:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong>* <strong>operator<\/strong> new(std::size_t, std::align_val_t);\n<strong>void<\/strong>* <strong>operator<\/strong> <strong>new<\/strong>&#91;](std::size_t, std::align_val_t);\n<strong>void<\/strong> <strong>operator<\/strong> delete(<strong>void<\/strong>*, std::align_val_t);\n<strong>void<\/strong> <strong>operator<\/strong> <strong>delete<\/strong>&#91;](<strong>void<\/strong>*, std::align_val_t);\n<strong>void<\/strong> <strong>operator<\/strong> delete(<strong>void<\/strong>*, std::size_t, std::align_val_t);\n<strong>void<\/strong> <strong>operator<\/strong> <strong>delete<\/strong>&#91;](<strong>void<\/strong>*, std::size_t, std::align_val_t);\n<\/code><\/pre>\n\n\n\n<p>See more in&nbsp;<a href=\"https:\/\/www.cppstories.com\/2019\/08\/newnew-align\/\">New new() &#8211; The C++17\u2019s Alignment Parameter for Operator new() &#8211; C++ Stories<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"__has_include-in-preprocessor-conditionals\"><code>__has_include<\/code>&nbsp;in preprocessor conditionals&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#__has_include-in-preprocessor-conditionals\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0061r1.html\">P0061R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 5.0<\/th><th>Clang: yes<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>This feature allows a C++ program to directly, reliably and portably determine whether or not a library header is available for inclusion.<\/p>\n\n\n\n<p>Example: This demonstrates a way to use a library optional facility only if it is available.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>#if __has_include(&lt;optional&gt;)\n<\/strong><strong>#  include &lt;optional&gt;\n<\/strong><strong>#  define have_optional 1\n<\/strong><strong>#elif __has_include(&lt;experimental\/optional&gt;)\n<\/strong><strong>#  include &lt;experimental\/optional&gt;\n<\/strong><strong>#  define have_optional 1\n<\/strong><strong>#  define experimental_optional 1\n<\/strong><strong>#else\n<\/strong><strong>#  define have_optional 0\n<\/strong><strong>#endif\n<\/strong><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"template-argument-deduction-for-class-templates\">Template argument deduction for class templates&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#template-argument-deduction-for-class-templates\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0091r3\">P0091R3<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 5<\/th><th>MSVC: VS 2017 15.7<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Before C++17, template deduction worked for functions but not for classes. For instance, the following code was legal:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> f(std::pair&lt;<strong>int<\/strong>, <strong>char<\/strong>&gt;);\n\nf(std::make_pair(42, 'z'));\n<\/code><\/pre>\n\n\n\n<p>because&nbsp;<code>std::make_pair<\/code>&nbsp;is a&nbsp;<em>template function<\/em>&nbsp;(so we can perform teplate deduction). But the following wasn\u2019t:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> f(std::pair&lt;<strong>int<\/strong>, <strong>char<\/strong>&gt;);\n\nf(std::pair(42, 'z'));\n<\/code><\/pre>\n\n\n\n<p>Although it is semantically equivalent. This was not legal because&nbsp;<code>std::pair<\/code>&nbsp;is a&nbsp;<em>template class<\/em>, and template classes could not apply type deduction in their initialization.<\/p>\n\n\n\n<p>So before C++17 one has to write out the types explicitly, even though this does not add any new information:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>void<\/strong> f(std::pair&lt;<strong>int<\/strong>, <strong>char<\/strong>&gt;);\n\nf(std::pair&lt;<strong>int<\/strong>, <strong>char<\/strong>&gt;(42, 'z'));\n<\/code><\/pre>\n\n\n\n<p>This is fixed in C++17 where template class constructors can deduce type parameters. The syntax for constructing such template classes is therefore consistent with the syntax for constructing non-template classes.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/06\/cpp17-details-templates.html#template-argument-deduction-for-class-templates\">Bartek\u2019s coding blog: C++17 in details: Templates<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=dEBQL4KPSk8\">A 4 min episode of C++ Weekly on class template argument type deduction<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=-3fVp0U4xi0\">A 4 min episode of C++ Weekly on deduction guides<\/a><\/li><li><a href=\"https:\/\/arne-mertz.de\/2017\/06\/class-template-argument-deduction\/\">Modern C++ Features &#8211; Class Template Argument Deduction &#8211;<\/a><\/li><li><a href=\"https:\/\/akrzemi1.wordpress.com\/2018\/12\/09\/deducing-your-intentions\/\">Deducing your intentions | Andrzej\u2019s C++ blog<\/a><\/li><li><a href=\"https:\/\/quuxplusone.github.io\/blog\/2018\/12\/09\/wctad\/\">_Contra_ CTAD \u2013 Arthur O\u2019Dwyer \u2013 Stuff mostly about C++<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"non-type-template-parameters-with-auto-type\">Non-type template parameters with auto type&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#non-type-template-parameters-with-auto-type\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0127r2\">P0127R2<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.7<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Automatically deduce type on non-type template parameters.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>auto<\/strong> value&gt; <strong>void<\/strong> f() { }\nf&lt;10&gt;();               <em>\/\/ deduces int\n<\/em><\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/herbsutter.com\/2016\/06\/30\/trip-report-summer-iso-c-standards-meeting-oulu\/\">Trip report: Summer ISO C++ standards meeting (Oulu) | Sutter\u2019s Mill<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"guaranteed-copy-elision\">Guaranteed copy elision&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#guaranteed-copy-elision\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0135r1\">P0135R1<\/a><\/p>\n\n\n\n<p>Copy elision for temporary objects, not for Named RVO.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.6<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code><em>\/\/ based on P0135R0\n<\/em><em><\/em><strong>struct<\/strong> <strong>NonMoveable<\/strong> \n{\n  NonMoveable(<strong>int<\/strong>);\n  <em>\/\/ no copy or move constructor:\n<\/em><em><\/em>  NonMoveable(<strong>const<\/strong> NonMoveable&amp;) = <strong>delete<\/strong>;\n  NonMoveable(NonMoveable&amp;&amp;) = <strong>delete<\/strong>;\n\n  std::array&lt;<strong>int<\/strong>, 1024&gt; arr;\n};\n\nNonMoveable make() \n{\n  <strong>return<\/strong> NonMoveable(42);\n}\n\n<em>\/\/ construct the object:\n<\/em><em><\/em><strong>auto<\/strong> largeNonMovableObj = make();\n<\/code><\/pre>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/06\/cpp17-details-clarifications.html#guaranteed-copy-elision\">Bartek\u2019s coding blog: C++17 in details: language clarifications<\/a><\/li><li><a href=\"https:\/\/jonasdevlieghere.com\/guaranteed-copy-elision\/\">Jonas Devlieghere: Guaranteed Copy Elision<\/a><\/li><li><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/guaranteed-copy-elision-does-not-elide-copies\/\">Guaranteed Copy Elision Does Not Elide Copies &#8211; C++ Team Blog<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"new-specification-for-inheriting-constructors-dr1941-et-al\">New specification for inheriting constructors (DR1941 et al)&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#new-specification-for-inheriting-constructors-dr1941-et-al\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0136r1\">P0136R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: VS 2017 15.7<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>More description and reasoning in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0136r0.html\">P0136R0<\/a>. Some excerpts below:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>An inheriting constructor does not act like any other form of using-declaration. All other using-declarations make some set of declarations visible to name lookup in another context, but an inheriting constructor declaration declares a new constructor that merely delegates to the original.<\/p><\/blockquote>\n\n\n\n<p>This feature changes inheriting constructor declaration from declaring a set of new constructors, to making a set of base class constructors visible in a derived class as if they were derived class constructors. (When such a constructor is used, the additional derived class subobjects will also be implicitly constructed as if by a defaulted default constructor). Put another way: make inheriting a constructor act just like inheriting any other base class member, to the extent possible.<\/p>\n\n\n\n<p>This change does affect the meaning and validity of some programs, but these changes improve the consistency and comprehensibility of C++.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em>\/\/ Hiding works the same as for other member\n<\/em><em>\/\/ using-declarations in the presence of default arguments\n<\/em><em><\/em><strong>struct<\/strong> <strong>A<\/strong> {\n  A(<strong>int<\/strong> a, <strong>int<\/strong> b = 0);\n  <strong>void<\/strong> f(<strong>int<\/strong> a, <strong>int<\/strong> b = 0);\n};\n<strong>struct<\/strong> <strong>B<\/strong> : A {\n  B(<strong>int<\/strong> a);      <strong>using<\/strong> A::A;\n  <strong>void<\/strong> f(<strong>int<\/strong> a); <strong>using<\/strong> A::f;\n};\n<strong>struct<\/strong> <strong>C<\/strong> : A {\n  C(<strong>int<\/strong> a, <strong>int<\/strong> b = 0);      <strong>using<\/strong> A::A;\n  <strong>void<\/strong> f(<strong>int<\/strong> a, <strong>int<\/strong> b = 0); <strong>using<\/strong> A::f;\n};\n\nB b(0); <em>\/\/ was ok, now ambiguous\n<\/em><em><\/em>b.f(0); <em>\/\/ ambiguous (unchanged)\n<\/em><em><\/em>\nC c(0); <em>\/\/ was ambiguous, now ok\n<\/em><em><\/em>c.f(0); <em>\/\/ ok (unchanged)\n<\/em><em><\/em>\n<em>\/\/ Inheriting constructor parameters are no longer copied\n<\/em><em><\/em><strong>struct<\/strong> <strong>A<\/strong> { A(<strong>const<\/strong> A&amp;) = <strong>delete<\/strong>; A(<strong>int<\/strong>); };\n<strong>struct<\/strong> <strong>B<\/strong> { B(A); <strong>void<\/strong> f(A); };\n<strong>struct<\/strong> <strong>C<\/strong> : B { <strong>using<\/strong> B::B; <strong>using<\/strong> B::f; };\nC c({0}); <em>\/\/ was ill-formed, now ok (no copy made)\n<\/em><em><\/em>c.f({0}); <em>\/\/ ok (unchanged)\n<\/em><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"direct-list-initialization-of-enumerations\">Direct-list-initialization of enumerations&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#direct-list-initialization-of-enumerations\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0138r2.pdf\">P0138R2<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Allows to initialize enum class with a fixed underlying type:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>enum<\/strong> <strong>class<\/strong> <strong>Handle<\/strong> : <strong>uint32_t<\/strong> { Invalid = 0 };\nHandle h { 42 }; <em>\/\/ OK\n<\/em><\/code><\/pre>\n\n\n\n<p>Allows to create&nbsp;<code>strong types<\/code>&nbsp;that are easy to use\u2026<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"stricter-expression-evaluation-order\">Stricter expression evaluation order&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stricter-expression-evaluation-order\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0145r3\">P0145R3<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.7<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>In a nutshell, given an expression such as&nbsp;<code>f(a, b, c)<\/code>, the order in which the sub-expressions f, a, b, c (which are of arbitrary shapes) are evaluated is left unspecified by the standard.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em>\/\/ unspecified behaviour below!\n<\/em><em><\/em>f(i++, i);\n\nv&#91;i] = i++;\n\nstd::map&lt;<strong>int<\/strong>, <strong>int<\/strong>&gt; m;\nm&#91;0] = m.size(); <em>\/\/ {{0, 0}} or {{0, 1}} ?\n<\/em><\/code><\/pre>\n\n\n\n<p>Summary of changes:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Postfix expressions are evaluated from left to right. This includes functions calls and member selection expressions.<\/li><li>Assignment expressions are evaluated from right to left. This includes compound assignments.<\/li><li>Operands to shift operators are evaluated from left to right.<\/li><\/ul>\n\n\n\n<p>See more in:&nbsp;<a href=\"https:\/\/www.cppstories.com\/2021\/evaluation-order-cpp17\/\">Stricter Expression Evaluation Order in C++17 &#8211; C++ Stories<\/a><\/p>\n\n\n\n<p>Reference:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/06\/cpp17-details-clarifications.html#stricter-expression-evaluation-order\">Bartek\u2019s coding blog: C++17 in details: language clarifications<\/a><\/li><li><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/eval_order\">C++ Order of evaluation, cppreference<\/a><\/li><li><a href=\"http:\/\/stackoverflow.com\/questions\/38501587\/what-are-the-evaluation-order-guarantees-introduced-by-c17\">SO: What are the evaluation order guarantees introduced by C++17?<\/a><\/li><li><a href=\"http:\/\/www.fluentcpp.com\/2017\/05\/09\/compact-code-becomes-buggy-code-order-evaluations\/\">How compact code can become buggy code: getting caught by the order of evaluations, Fluent C++<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"constexpr-lambda-expressions\"><code>constexpr<\/code>&nbsp;lambda expressions&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#constexpr-lambda-expressions\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0170r1\">P0170R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 5<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p><code>constexpr<\/code>&nbsp;can be used in the context of lambdas.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>constexpr<\/strong> <strong>auto<\/strong> ID = &#91;] (<strong>int<\/strong> n)  { <strong>return<\/strong> n; };\n<strong>constexpr<\/strong> <strong>int<\/strong> I = ID(3);\n<strong>static_assert<\/strong>(I == 3);\n\n<strong>constexpr<\/strong> <strong>int<\/strong> AddEleven(<strong>int<\/strong> n) {\n  <em>\/\/ Initialization of the 'data member' for n can\n<\/em><em><\/em>  <em>\/\/ occur within a constant expression since 'n' is\n<\/em><em><\/em>  <em>\/\/ of literal type.\n<\/em><em><\/em>  <strong>return<\/strong> &#91;n] { <strong>return<\/strong> n + 11; }();\n}\n<strong>static_assert<\/strong>(AddEleven(5) == 16);\n<\/code><\/pre>\n\n\n\n<p>Articles<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.youtube.com\/watch?v=kmza9U_niq4\">A 5 min episode of Jason Turner\u2019s C++ Weekly about constexpr lambdas<\/a><\/li><li><a href=\"https:\/\/maitesin.github.io\/Lambda_comparison\/\">Lambda expression comparison between C++11, C++14 and C++17<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"different-begin-and-end-types-in-range-based-for\">Different begin and end types in range-based for&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#different-begin-and-end-types-in-range-based-for\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0184r0.html\">P0184R0<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.6<\/th><th>MSVC: 15.0 Preview 5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Changing the definition of range based for from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n   <strong>auto<\/strong> &amp;&amp; __range = <strong>for<\/strong>-range-initializer;\n   <strong>for<\/strong> ( <strong>auto<\/strong> __begin = begin-expr,\n              __end = end-expr;\n              __begin != __end;\n              ++__begin ) {\n        <strong>for<\/strong>-range-declaration = *__begin;\n        statement\n   }\n}\n<\/code><\/pre>\n\n\n\n<p>Into:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  <strong>auto<\/strong> &amp;&amp; __range = <strong>for<\/strong>-range-initializer;\n  <strong>auto<\/strong> __begin = begin-expr;\n  <strong>auto<\/strong> __end = end-expr;\n  <strong>for<\/strong> ( ; __begin != __end; ++__begin ) {\n    <strong>for<\/strong>-range-declaration = *__begin;\n    statement\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Types of&nbsp;<code>__begin<\/code>&nbsp;and&nbsp;<code>__end<\/code>&nbsp;might be different; only the comparison operator is required. This little change allows Range TS users a better experience.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallthrough-attribute\"><code>[[fallthrough]]<\/code>&nbsp;attribute&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#fallthrough-attribute\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0188r1.pdf\">P0188R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.0 Preview 4<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Indicates that a fallthrough in a switch statement is intentional and a warning should not be issued for it. More details in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0068r0.pdf\">P0068R0<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>switch<\/strong> (c) {\n<strong>case<\/strong> 'a':\n    f(); <em>\/\/ Warning emitted, fallthrough is perhaps a programmer error\n<\/em><em><\/em><strong>case<\/strong> 'b':\n    g();\n&#91;&#91;fallthrough]]; <em>\/\/ Warning suppressed, fallthrough is intentional\n<\/em><em><\/em><strong>case<\/strong> 'c':\n    h();\n}\n<\/code><\/pre>\n\n\n\n<p>See more in&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/07\/cpp17-in-details-attributes\/\">C++17 in details: Attributes &#8211; C++ Stories<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"nodiscard-attribute\"><code>[[nodiscard]]<\/code>&nbsp;attribute&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#nodiscard-attribute\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0189r1.pdf\">P0189R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p><code>[[nodiscard]]<\/code>&nbsp;is used to stress that the return value of a function is not to be discarded, on pain of a compiler warning. More details in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0068r0.pdf\">P0068R0<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;&#91;nodiscard]] <strong>int<\/strong> foo();\n<strong>void<\/strong> bar() {\n    foo(); <em>\/\/ Warning emitted, return value of a nodiscard function is discarded\n<\/em><em><\/em>}\n<\/code><\/pre>\n\n\n\n<p>This attribute can also be applied to types in order to mark all functions which return that type as&nbsp;<code>[[nodiscard]]<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;&#91;nodiscard]] <strong>struct<\/strong> <strong>DoNotThrowMeAway<\/strong>{};\nDoNotThrowMeAway i_promise();\n<strong>void<\/strong> oops() {\n    i_promise(); <em>\/\/ Warning emitted, return value of a nodiscard function is discarded\n<\/em><em><\/em>}\n<\/code><\/pre>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/11\/nodiscard.html\">Bartek\u2019s coding blog: Enforcing code contracts with [[nodiscard]]<\/a><\/li><li><a href=\"https:\/\/www.youtube.com\/watch?v=l_5PF3GQLKc\">A 4 min video about nodiscard in Jason Turner\u2019s C++ Weekly<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"maybe_unused-attribute\"><code>[[maybe_unused]]<\/code>&nbsp;attribute&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#maybe_unused-attribute\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0212r1.pdf\">P0212R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Suppresses compiler warnings about unused entities when they are declared with&nbsp;<code>[[maybe_unused]]<\/code>. More details in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0068r0.pdf\">P0068R0<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>                 <strong>static<\/strong> <strong>void<\/strong> impl1() { ... } <em>\/\/ Compilers may warn about this\n<\/em><em><\/em>&#91;&#91;maybe_unused]] <strong>static<\/strong> <strong>void<\/strong> impl2() { ... } <em>\/\/ Warning suppressed\n<\/em><em><\/em>\n<strong>void<\/strong> foo() {\n                      <strong>int<\/strong> x = 42; <em>\/\/ Compilers may warn about this\n<\/em><em><\/em>     &#91;&#91;maybe_unused]] <strong>int<\/strong> y = 42; <em>\/\/ Warning suppressed\n<\/em><em><\/em>}\n<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=WSPmNL9834U\">A 3 min video about maybe_unused in Jason Turner\u2019s C++ Weekly<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"ignore-unknown-attributes\">Ignore unknown attributes&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#ignore-unknown-attributes\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0283r2\">P0283R2<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: Yes<\/th><th>Clang: 3.9<\/th><th>MSVC: VS 2017 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Clarifies that implementations should ignore any attribute namespaces which they do not support, as this used to be unspecified. More details in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0283r1.pdf\">P0283R1<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><em>\/\/compilers which don't support MyCompilerSpecificNamespace will ignore this attribute\n<\/em><em><\/em>&#91;&#91;MyCompilerSpecificNamespace::do_special_thing]]\n<strong>void<\/strong> foo();\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"pack-expansions-in-using-declarations\">Pack expansions in using-declarations&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#pack-expansions-in-using-declarations\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0195r2\">P0195R2<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.7<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Allows you to inject names with&nbsp;<em>using-declarations<\/em>&nbsp;from all types in a parameter pack.<\/p>\n\n\n\n<p>In order to expose&nbsp;<code>operator()<\/code>&nbsp;from all base classes in a variadic template, we used to have to resort to recursion:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>typename<\/strong> T, <strong>typename<\/strong>... Ts&gt;\n<strong>struct<\/strong> <strong>Overloader<\/strong> : T, Overloader&lt;Ts...&gt; {\n    <strong>using<\/strong> T::<strong>operator<\/strong>();\n    <strong>using<\/strong> Overloader&lt;Ts...&gt;::<strong>operator<\/strong>();\n    <em>\/\/ &#91;\u2026]\n<\/em><em><\/em>};\n\n<strong>template<\/strong> &lt;<strong>typename<\/strong> T&gt; <strong>struct<\/strong> <strong>Overloader<\/strong>&lt;T&gt; : T {\n    <strong>using<\/strong> T::<strong>operator<\/strong>();\n};\n<\/code><\/pre>\n\n\n\n<p>Now we can simply expand the parameter pack in the&nbsp;<em>using-declaration<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>typename<\/strong>... Ts&gt;\n<strong>struct<\/strong> <strong>Overloader<\/strong> : Ts... {\n    <strong>using<\/strong> Ts::<strong>operator<\/strong>()...;\n    <em>\/\/ &#91;\u2026]\n<\/em><em><\/em>};\n<\/code><\/pre>\n\n\n\n<p>See more in&nbsp;<a href=\"https:\/\/www.cppstories.com\/2019\/02\/2lines3featuresoverload.html\/\">2 Lines Of Code and 3 C++17 Features &#8211; The overload Pattern &#8211; C++ Stories<\/a><\/p>\n\n\n\n<p>Remarks<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Implemented in GCC 7.0, see&nbsp;<a href=\"https:\/\/github.com\/gcc-mirror\/gcc\/commit\/caba101ff33a763b444090b9c073bd84972ee552\">this change<\/a>.<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"structured-binding-declarations\">Structured Binding Declarations&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#structured-binding-declarations\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0217r3\">P0217R3<\/a><br><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2017\/p0615r0.html\">P0615R0: Renaming for structured bindings<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Helps when using tuples as a return type. It will automatically create variables and&nbsp;<code>tie<\/code>&nbsp;them. More details in&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0144r0.pdf\">P0144R0<\/a>.<\/p>\n\n\n\n<p>The name \u201cDecomposition Declaration\u201d was also used, but finally the standard agrees to use \u201cStructured Binding Declarations\u201d (section 11.5)<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>int<\/strong> a = 0;\n<strong>double<\/strong> b = 0.0;\n<strong>long<\/strong> c = 0;\nstd::tie(a, b, c) = tuple; <em>\/\/ a, b, c need to be declared first\n<\/em><\/code><\/pre>\n\n\n\n<p>Now we can write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>auto<\/strong> &#91; a, b, c ] = tuple;\n<\/code><\/pre>\n\n\n\n<p>Such expressions also work on structs, pairs, and arrays.<\/p>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/skebanga.github.io\/structured-bindings\/\">Steve Lorimer, C++17 Structured Bindings<\/a><\/li><li><a href=\"http:\/\/jrb-programming.blogspot.fr\/2016\/02\/emulating-c17-structured-binding-in-c14.html\">jrb-programming, Emulating C++17 Structured Bindings in C++14<\/a><\/li><li><a href=\"https:\/\/tartanllama.github.io\/c++\/2016\/07\/20\/structured-bindings\/\">Simon Brand, Adding C++17 decomposition declaration support to your classes<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"hexadecimal-floating-point-literals\">Hexadecimal floating-point literals&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#hexadecimal-floating-point-literals\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0245r1\">P0245R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 3.0<\/th><th>Clang: Yes<\/th><th>MSVC: VS 2017 15.3t<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Allows to express some special floating point values, for example, the smallest normal IEEE-754 single precision value is readily written as&nbsp;<code>0x1.0p-126<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"init-statements-for-if-and-switch\">init-statements for if and switch&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#init-statements-for-if-and-switch\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0305r1\">P0305R1<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>New versions of the if and switch statements for C++:<\/p>\n\n\n\n<p><code>if (init; condition)<\/code>&nbsp;and&nbsp;<code>switch (init; condition)<\/code>.<\/p>\n\n\n\n<p>This should simplify the code. For example, previously you had to write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    <strong>auto<\/strong> val = GetValue();\n    <strong>if<\/strong> (condition(val))\n        <em>\/\/ on success\n<\/em><em><\/em>    <strong>else<\/strong>\n        <em>\/\/ on false...\n<\/em><em><\/em>}\n<\/code><\/pre>\n\n\n\n<p>Look, that&nbsp;<code>val<\/code>&nbsp;has a separate scope, without it it will \u2018leak\u2019.<\/p>\n\n\n\n<p>Now you can write:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>if<\/strong> (<strong>auto<\/strong> val = GetValue(); condition(val))\n    <em>\/\/ on success\n<\/em><em><\/em><strong>else<\/strong>\n    <em>\/\/ on false...\n<\/em><\/code><\/pre>\n\n\n\n<p><code>val<\/code>&nbsp;is visible only inside the&nbsp;<code>if<\/code>&nbsp;and&nbsp;<code>else<\/code>&nbsp;statements, so it doesn\u2019t \u2018leak\u2019.&nbsp;<code>condition<\/code>&nbsp;might be any condition, not only if&nbsp;<code>val<\/code>&nbsp;is true\/false.<\/p>\n\n\n\n<p>Examples:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.youtube.com\/watch?v=AiXU5EuLZgc&amp;feature=youtu.be\">C++ Weekly &#8211; Ep 21 C++17\u2019s&nbsp;<code>if<\/code>&nbsp;and&nbsp;<code>switch<\/code>&nbsp;Init Statements<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"inline-variables\">Inline variables&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#inline-variables\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0386r2\">P0386R2<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>Previously only methods\/functions could be specified as&nbsp;<code>inline<\/code>, now you can do the same with variables, inside a header file.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>A variable declared inline has the same semantics as a function declared inline: it can be defined, identically, in multiple translation units, must be defined in every translation unit in which it is used, and the behavior of the program is as if there is exactly one variable.<\/p><\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>struct<\/strong> <strong>MyClass<\/strong>\n{\n    <strong>static<\/strong> <strong>const<\/strong> <strong>int<\/strong> sValue;\n};\n\n<strong>inline<\/strong> <strong>int<\/strong> <strong>const<\/strong> MyClass::sValue = 777;\n<\/code><\/pre>\n\n\n\n<p>Or even:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>struct<\/strong> <strong>MyClass<\/strong>\n{\n    <strong>inline<\/strong> <strong>static<\/strong> <strong>const<\/strong> <strong>int<\/strong> sValue = 777;\n};\n<\/code><\/pre>\n\n\n\n<p>Articles<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2019\/08\/17smallercpp17features\/#2-inline-variables\">17 Smaller but Handy C++17 Features &#8211; C++ Stories<\/a>&nbsp;&#8211; inline variables<\/li><li><a href=\"http:\/\/stackoverflow.com\/questions\/38043442\/what-is-an-inline-variable-and-what-is-it-useful-for\">SO: What is an inline variable and what is it useful for?<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"dr-matching-of-template-template-arguments-excludes-compatible-templates\">DR: Matching of template template-arguments excludes compatible templates&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#dr-matching-of-template-template-arguments-excludes-compatible-templates\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/wg21.link\/p0522r0\">P0522R0<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 4.0<\/th><th>MSVC: VS 2017 15.5<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>This feature resolves&nbsp;<a href=\"http:\/\/open-std.org\/JTC1\/SC22\/WG21\/docs\/papers\/2015\/n4457.html#150\">Core issue CWG 150<\/a>.<\/p>\n\n\n\n<p>From the paper:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>This paper allows a template template-parameter to bind to a template argument whenever the template parameter is at least as specialized as the template argument. This implies that any template argument list that can legitimately be applied to the template template-parameter is also applicable to the argument template.<\/p><\/blockquote>\n\n\n\n<p>Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>template<\/strong> &lt;<strong>int<\/strong>&gt; <strong>class<\/strong>&gt; <strong>void<\/strong> FI();\n<strong>template<\/strong> &lt;<strong>template<\/strong> &lt;<strong>auto<\/strong>&gt; <strong>class<\/strong>&gt; <strong>void<\/strong> FA();\n<strong>template<\/strong> &lt;<strong>auto<\/strong>&gt; <strong>struct<\/strong> <strong>SA<\/strong> { <em>\/* ... *\/<\/em> };\n<strong>template<\/strong> &lt;<strong>int<\/strong>&gt; <strong>struct<\/strong> <strong>SI<\/strong> { <em>\/* ... *\/<\/em> };\nFI&lt;SA&gt;();  <em>\/\/ OK; error before this paper\n<\/em><em><\/em>FA&lt;SI&gt;();  <em>\/\/ error\n<\/em><em><\/em>\n<strong>template<\/strong> &lt;<strong>template<\/strong> &lt;<strong>typename<\/strong>&gt; <strong>class<\/strong>&gt; <strong>void<\/strong> FD();\n<strong>template<\/strong> &lt;<strong>typename<\/strong>, <strong>typename<\/strong> = <strong>int<\/strong>&gt; <strong>struct<\/strong> <strong>SD<\/strong> { <em>\/* ... *\/<\/em> };\nFD&lt;SD&gt;();  <em>\/\/ OK; error before this paper (CWG 150)\n<\/em><\/code><\/pre>\n\n\n\n<p>(Adapted from the&nbsp;<a href=\"https:\/\/www.reddit.com\/r\/cpp\/comments\/5osck2\/c_17_features\/dcm7eq4\/\">comment<\/a>&nbsp;by&nbsp;<a href=\"https:\/\/www.reddit.com\/user\/IncongruentModulo1\">IncongruentModulo1<\/a>)<\/p>\n\n\n\n<p>For a useful example, consider something like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>template<\/strong> &lt;<strong>typename<\/strong>&gt; <strong>typename<\/strong> Container&gt;\n<strong>struct<\/strong> <strong>A<\/strong>\n{\n    Container&lt;<strong>int<\/strong>&gt;    m_ints;\n    Container&lt;<strong>double<\/strong>&gt; m_doubles;\n};\n<\/code><\/pre>\n\n\n\n<p>In C++14 and earlier,&nbsp;<code>A&lt;std::vector&gt;<\/code>&nbsp;wouldn\u2019t be valid (ignoring the typename and not class before container) since&nbsp;<code>std::vector<\/code>&nbsp;is declared as:<\/p>\n\n\n\n<p><code>template &lt;typename T, typename Allocator = std::allocator&lt;T&gt;&gt; class vector;<\/code><\/p>\n\n\n\n<p>This change resolves that issue. Before, you would need to declare template&nbsp;<code>&lt;template &lt;typename...&gt; typename Container&gt;<\/code>, which is more permissive and moves the error to a less explicit line (namely the declaration of&nbsp;<code>m_ints<\/code>&nbsp;wherever the&nbsp;<code>struct A<\/code>&nbsp;is implemented \/declared, instead of where the struct is instantiated with the wrong template type.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"stduncaught_exceptions\"><code>std::uncaught_exceptions()<\/code>&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stduncaught_exceptions\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4259\">N4259<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 6.0<\/th><th>Clang: 3.7<\/th><th>MSVC: 14.0<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>More background in the original paper:&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4152\">PDF: N4152<\/a>&nbsp;and&nbsp;<a href=\"http:\/\/www.gotw.ca\/gotw\/047.htm\">GOTW issue 47: Uncaught Exceptions<\/a>.<\/p>\n\n\n\n<p>The function returns the number of uncaught exception objects in the current thread.<\/p>\n\n\n\n<p>This might be useful when implementing proper Scope Guards that works also during stack unwinding.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>A type that wants to know whether its destructor is being run to unwind this object can query uncaught_exceptions in its constructor and store the result, then query uncaught_exceptions again in its destructor; if the result is different, then this destructor is being invoked as part of stack unwinding due to a new exception that was thrown later than the object\u2019s construction<\/p><\/blockquote>\n\n\n\n<p>The above quote comes from&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2014\/n4152\">PDF: N4152<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"constexpr-if-statements\"><code>constexpr<\/code>&nbsp;if-statements&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#constexpr-if-statements\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0292r2.html\">P0292R2<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>GCC: 7.0<\/th><th>Clang: 3.9<\/th><th>MSVC: 15.3<\/th><\/tr><\/thead><\/table><\/figure>\n\n\n\n<p>The static-if for C++! This allows you to discard branches of an if statement at compile-time based on a constant expression condition.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>if<\/strong> constexpr(cond)\n     statement1; <em>\/\/ Discarded if cond is false\n<\/em><em><\/em><strong>else<\/strong>\n     statement2; <em>\/\/ Discarded if cond is true\n<\/em><\/code><\/pre>\n\n\n\n<p>This removes a lot of the necessity for tag dispatching and SFINAE:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"sfinae\">SFINAE<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>typename<\/strong> T, std::enable_if_t&lt;std::is_arithmetic&lt;T&gt;{}&gt;* = <strong>nullptr<\/strong>&gt;\n<strong>auto<\/strong> get_value(T t) {<em>\/*...*\/<\/em>}\n\n<strong>template<\/strong> &lt;<strong>typename<\/strong> T, std::enable_if_t&lt;!std::is_arithmetic&lt;T&gt;{}&gt;* = <strong>nullptr<\/strong>&gt;\n<strong>auto<\/strong> get_value(T t) {<em>\/*...*\/<\/em>}\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"tag-dispatching\">Tag dispatching<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>typename<\/strong> T&gt;\n<strong>auto<\/strong> get_value(T t, std::true_type) {<em>\/*...*\/<\/em>}\n\n<strong>template<\/strong> &lt;<strong>typename<\/strong> T&gt;\n<strong>auto<\/strong> get_value(T t, std::false_type) {<em>\/*...*\/<\/em>}\n\n<strong>template<\/strong> &lt;<strong>typename<\/strong> T&gt;\n<strong>auto<\/strong> get_value(T t) {\n    <strong>return<\/strong> get_value(t, std::is_arithmetic&lt;T&gt;{});\n}\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"if-constexpr\">if constexpr<\/h4>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>template<\/strong> &lt;<strong>typename<\/strong> T&gt;\n<strong>auto<\/strong> get_value(T t) {\n     <strong>if<\/strong> constexpr (std::is_arithmetic_v&lt;T&gt;) {\n         <em>\/\/...\n<\/em><em><\/em>     }\n     <strong>else<\/strong> {\n         <em>\/\/...\n<\/em><em><\/em>     }\n}\n<\/code><\/pre>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2018\/03\/ifconstexpr.html\">Bartek\u2019s coding blog: Simplify code with \u2018if constexpr\u2019 in C++17<\/a><\/li><li><a href=\"https:\/\/medium.com\/@LoopPerfect\/c-17-vs-c-14-if-constexpr-b518982bb1e2\">LoopPerfect Blog, C++17 vs C++14 &#8211; Round 1 &#8211; if-constexpr<\/a><\/li><li><a href=\"http:\/\/stackoverflow.com\/questions\/38304847\/constexpr-if-and-static-assert\">SO: constexpr if and&nbsp;<code>static_assert<\/code><\/a><\/li><li><a href=\"https:\/\/tartanllama.github.io\/c++\/2016\/12\/12\/if-constexpr\/\">Simon Brand: Simplifying templates and #ifdefs with if constexpr<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"library-features\">Library Features&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#library-features\">&nbsp;<\/a>&nbsp;<\/h2>\n\n\n\n<p>To get more details about library implementation I suggest those links:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2016\/01\/22\/vs-2015-update-2s-stl-is-c17-so-far-feature-complete\/\">VS 2015 Update 2\u2019s STL is C++17-so-far Feature Complete<\/a>&nbsp;&#8211; Jan 2016<\/li><li><a href=\"https:\/\/gcc.gnu.org\/onlinedocs\/libstdc++\/manual\/status.html#status.iso.201z\">libstdc++, C++ 201z status<\/a><\/li><li><a href=\"http:\/\/libcxx.llvm.org\/cxx1z_status.html\">libc++ C++1z Status<\/a><\/li><\/ul>\n\n\n\n<p>This section only mentions some of the most important parts of library changes, it would be too impractical to go into details of every little change.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"merged-the-library-fundamentals-1-ts-most-parts\">Merged: The Library Fundamentals 1 TS (most parts)&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-the-library-fundamentals-1-ts-most-parts\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"https:\/\/isocpp.org\/files\/papers\/p0220r1.html\">P0220R1<\/a><\/p>\n\n\n\n<p>We get the following items:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Tuples &#8211;&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#tuple.apply\">Calling a function with a tuple of arguments<\/a><\/li><li>Functional Objects &#8211;&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#func.searchers\">Searchers<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#optional\">Optional objects<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#any\">Class any<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#string.view\"><code>string_view<\/code><\/a><\/li><li>Memory:<ul><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#memory.smartptr\">Shared-ownership pointers<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#memory.resource\">Class memory_resource<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#memory.resource.global\">Access to program-wide memory_resource objects<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#memory.resource.pool\">Pool resource classes<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#memory.resource.monotonic.buffer\">Class monotonic_buffer_resource<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#memory.resource.aliases\">Alias templates using polymorphic memory resources<\/a><\/li><\/ul><\/li><li>Algorithms:<ul><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#alg.search\">Search<\/a><\/li><li><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4562.html#alg.random.sample\">Sampling<\/a><\/li><\/ul><\/li><li><code>shared_ptr<\/code>&nbsp;natively handles arrays: see&nbsp;<a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0414r2.html\">Merging shared_ptr changes from Library Fundamentals to C++17<\/a><\/li><\/ul>\n\n\n\n<p>The wording from those components comes from Library Fundamentals V2 to ensure the wording includes the latest corrections.<\/p>\n\n\n\n<p>Resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/marcoarena.wordpress.com\/2017\/01\/03\/string_view-odi-et-amo\/\">Marco Arena, string_view odi et amo<\/a><\/li><li><a href=\"https:\/\/www.cppstories.com\/2017\/09\/cpp17-details-utils.html\">Bartek\u2019s coding blog: C++17 in details: Standard Library Utilities<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"removal-of-some-deprecated-types-and-functions-including-stdauto_ptr-stdrandom_shuffle-and-old-function-adaptors\">Removal of some deprecated types and functions, including&nbsp;<code>std::auto_ptr<\/code>,&nbsp;<code>std::random_shuffle<\/code>, and old function adaptors&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#removal-of-some-deprecated-types-and-functions-including-stdauto_ptr-stdrandom_shuffle-and-old-function-adaptors\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/p0001r1.html\">N4190<\/a><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Function objects &#8211; unary_function\/binary_function, ptr_fun(), and mem_fun()\/mem_fun_ref()<\/li><li>Binders &#8211; bind1st()\/bind2nd()<\/li><li><strong>auto_ptr<\/strong><\/li><li>Random shuffle &#8211; random_shuffle(first, last) and random_shuffle(first, last, rng)<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"merged-the-parallelism-ts-aka-parallel-stl\">Merged: The Parallelism TS, a.k.a. \u201cParallel STL.\u201d,&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-the-parallelism-ts-aka-parallel-stl\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/isocpp.org\/files\/papers\/P0024R2.html\">P0024R2<\/a><\/p>\n\n\n\n<p>Parralel versions\/overloads of most of std algorithms. Plus a few new algorithms, like reduce, transform_reduce, for_each.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>std::vector&lt;<strong>int<\/strong>&gt; v = genLargeVector();\n\n<em>\/\/ standard sequential sort\n<\/em><em><\/em>std::sort(v.begin(), v.end());\n\n<em>\/\/ explicitly sequential sort\n<\/em><em><\/em>std::sort(std::seq, v.begin(), v.end());\n\n<em>\/\/ permitting parallel execution\n<\/em><em><\/em>std::sort(std::par, v.begin(), v.end());\n\n<em>\/\/ permitting vectorization as well\n<\/em><em><\/em>std::sort(std::par_unseq, v.begin(), v.end());\n<\/code><\/pre>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/08\/cpp17-details-parallel.html\">Bartek\u2019s coding blog: C++17 in details: Parallel Algorithms<\/a><\/li><li><a href=\"http:\/\/www.modernescpp.com\/index.php\/parallel-algorithm-of-the-standard-template-library\">Parallel Algorithm of the Standard Template Library &#8211; ModernesCpp.com<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"merged-file-system-ts\">Merged: File System TS,&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-file-system-ts\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"https:\/\/isocpp.org\/files\/papers\/P0218r1.html\">P0218R1<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>namespace<\/strong> fs = std::filesystem;\n\nfs::path pathToShow(<em>\/* ... *\/<\/em>);\ncout &lt;&lt; \"exists() = \" &lt;&lt; fs::exists(pathToShow) &lt;&lt; \"\\n\"\n     &lt;&lt; \"root_name() = \" &lt;&lt; pathToShow.root_name() &lt;&lt; \"\\n\"\n     &lt;&lt; \"root_path() = \" &lt;&lt; pathToShow.root_path() &lt;&lt; \"\\n\"\n     &lt;&lt; \"relative_path() = \" &lt;&lt; pathToShow.relative_path() &lt;&lt; \"\\n\"\n     &lt;&lt; \"parent_path() = \" &lt;&lt; pathToShow.parent_path() &lt;&lt; \"\\n\"\n     &lt;&lt; \"filename() = \" &lt;&lt; pathToShow.filename() &lt;&lt; \"\\n\"\n     &lt;&lt; \"stem() = \" &lt;&lt; pathToShow.stem() &lt;&lt; \"\\n\"\n     &lt;&lt; \"extension() = \" &lt;&lt; pathToShow.extension() &lt;&lt; \"\\n\";\n<\/code><\/pre>\n\n\n\n<p>Articles:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.cppstories.com\/2017\/08\/cpp17-details-filesystem.html\">Bartek\u2019s coding blog: C++17 in details: Filesystem<\/a><\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"merged-the-mathematical-special-functions-is\">Merged: The Mathematical Special Functions IS,&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#merged-the-mathematical-special-functions-is\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"https:\/\/isocpp.org\/files\/papers\/P0226R1.pdf\">PDF &#8211; WG21 P0226R1<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"improving-stdpairhttpencppreferencecomwcpputilitypair-and-stdtuplehttpencppreferencecomwcpputilitytuple\">Improving&nbsp;<a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/pair\">std::pair<\/a>&nbsp;and&nbsp;<a href=\"http:\/\/en.cppreference.com\/w\/cpp\/utility\/tuple\">std::tuple<\/a>&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#improving-stdpairhttpencppreferencecomwcpputilitypair-and-stdtuplehttpencppreferencecomwcpputilitytuple\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4387.html\">N4387<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"stdshared_mutexhttpencppreferencecomwcppthreadshared_mutex-untimed\"><a href=\"http:\/\/en.cppreference.com\/w\/cpp\/thread\/shared_mutex\"><code>std::shared_mutex<\/code><\/a>&nbsp;(untimed)&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stdshared_mutexhttpencppreferencecomwcppthreadshared_mutex-untimed\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4508.html\">N4508<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"stdvariant\"><code>std::variant<\/code>&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#stdvariant\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0088r2.html\">P0088R2<\/a><\/p>\n\n\n\n<p>Variant is a typesafe union that will report errors when you want to access something that\u2019s not currently inside the object.<\/p>\n\n\n\n<p>Notes:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Variant is not allowed to allocate additional (dynamic) memory.<\/li><li>A variant is not permitted to hold references, arrays, or the type&nbsp;<code>void<\/code>.<\/li><li>A variant is default initialized with the value of its first alternative.<\/li><li>If the first alternative type is not default constructible, then the variant must use std::monostate as the first alternative<\/li><\/ul>\n\n\n\n<p>Have a look at more example in a separate article:<\/p>\n\n\n\n<p><a href=\"https:\/\/www.cppstories.com\/2018\/06\/variant\/\">Everything You Need to Know About std::variant from C++17 &#8211; C++ Stories<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"splicing-maps-and-sets\">Splicing Maps and Sets&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#splicing-maps-and-sets\">&nbsp;<\/a>&nbsp;<\/h3>\n\n\n\n<p><a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2016\/p0083r2.pdf\">P0083R2<\/a><\/p>\n\n\n\n<p>From Herb Sutter,&nbsp;<a href=\"https:\/\/herbsutter.com\/2016\/06\/30\/trip-report-summer-iso-c-standards-meeting-oulu\/\">Oulu trip report<\/a>:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>You will now be able to directly move internal nodes from one node-based container directly into another container of the same type. Why is that important? Because it guarantees no memory allocation overhead, no copying of keys or values, and even no exceptions if the container\u2019s comparison function doesn\u2019t throw.<\/p><\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"contributors\">Contributors&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#contributors\">&nbsp;<\/a>&nbsp;<\/h2>\n\n\n\n<p>This is a place for you to be mentioned!<\/p>\n\n\n\n<p>Contributors:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/tartanllama.github.io\/\">Simon Brand<\/a><\/li><li><a href=\"http:\/\/www.fluentcpp.com\/\">Jonathan Boccara, Fluent{C++}<\/a><\/li><li><a href=\"https:\/\/twitter.com\/Kurdej\">Marek Kurdej<\/a><\/li><li>suggestions from r\/cpp thread:&nbsp;<a href=\"https:\/\/www.reddit.com\/r\/cpp\/comments\/5osck2\/c_17_features\/\"><code>c_17_features<\/code><\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"summary\">Summary&nbsp;<a href=\"https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/#summary\">&nbsp;<\/a>&nbsp;<\/h2>\n\n\n\n<p>Thanks for all the support with the list!<\/p>\n\n\n\n<p>There are still items that should be updated, but the list is mostly done.<\/p>\n\n\n\n<p>If you want to read more about C++17, have a look at my book (-17% less with this coupon code, till 10th December 2022)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Link: https:\/\/www.cppstories.com\/2017\/01\/cpp17features\/ Publication data: 10th October 2022 The ISO Committee accepted and published the C++17 Standard in December 2017. In this mega-long article, I\u2019ve built (with your help!) a list&#8230; <a class=\"read-more-link\" href=\"https:\/\/tbekk.com\/devstream\/blog\/2022\/10\/11\/all-major-c17-features-you-should-know\/\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,155],"tags":[85],"class_list":["post-685","post","type-post","status-publish","format-standard","hentry","category-development","category-languages","tag-c17"],"_links":{"self":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/comments?post=685"}],"version-history":[{"count":2,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/685\/revisions"}],"predecessor-version":[{"id":687,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/685\/revisions\/687"}],"wp:attachment":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/media?parent=685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/categories?post=685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/tags?post=685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}