[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-71521":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":10,"languages":10,"totalLinesOfCode":10,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":15,"starSnapshotCount":15,"syncStatus":35,"lastSyncTime":36,"discoverSource":37},71521,"modern-cpp-features","AnthonyCalandra\u002Fmodern-cpp-features","AnthonyCalandra","A cheatsheet of modern C++ language and library features.","",null,21749,2264,791,3,0,24,57,85,72,45,"MIT License",false,"master",true,[26,27,28,29,30,31],"cpp","cpp11","cpp14","cpp17","cpp20","cpp23","2026-06-12 02:02:53","# C++23\u002F20\u002F17\u002F14\u002F11\n\n## Overview\n\nC++23 includes the following new language features:\n- [consteval if](#consteval-if)\n- [deducing `this`](#deducing-this)\n- [multidimensional subscript operator](#multidimensional-subscript-operator)\n- [increasing range-based `for` safety](#increasing-range-based-for-safety)\n\nC++23 includes the following new library features:\n- [stacktrace library](#stacktrace-library)\n- [contains for strings and string views](#contains-for-strings-and-string-views)\n- [std::to_underlying](#stdto_underlying)\n- [`spanstream`](#spanstream)\n- [input\u002Foutput pointers](#inputoutput-pointers)\n- [monadic operations for `std::optional`](monadic-operations-for-stdoptional)\n- [`std::expected`](#stdexpected)\n- [`std::unreachable`](#stdunreachable)\n\nC++20 includes the following new language features:\n- [coroutines](#coroutines)\n- [concepts](#concepts)\n- [three-way comparison](#three-way-comparison)\n- [designated initializers](#designated-initializers)\n- [template syntax for lambdas](#template-syntax-for-lambdas)\n- [range-based for loop with initializer](#range-based-for-loop-with-initializer)\n- [\\[\\[likely\\]\\] and \\[\\[unlikely\\]\\] attributes](#likely-and-unlikely-attributes)\n- [deprecate implicit capture of this](#deprecate-implicit-capture-of-this)\n- [class types in non-type template parameters](#class-types-in-non-type-template-parameters)\n- [constexpr virtual functions](#constexpr-virtual-functions)\n- [explicit(bool)](#explicitbool)\n- [immediate functions](#immediate-functions)\n- [using enum](#using-enum)\n- [lambda capture of parameter pack](#lambda-capture-of-parameter-pack)\n- [char8_t](#char8_t)\n- [constinit](#constinit)\n- [\\_\\_VA\\_OPT\\_\\_](#__VA_OPT__)\n\nC++20 includes the following new library features:\n- [text formatting](#text-formatting)\n- [concepts library](#concepts-library)\n- [synchronized buffered outputstream](#synchronized-buffered-outputstream)\n- [std::span](#stdspan)\n- [bit operations](#bit-operations)\n- [math constants](#math-constants)\n- [std::is_constant_evaluated](#stdis_constant_evaluated)\n- [std::make_shared supports arrays](#stdmake_shared-supports-arrays)\n- [starts_with and ends_with on strings](#starts_with-and-ends_with-on-strings)\n- [check if associative container has element](#check-if-associative-container-has-element)\n- [std::bit_cast](#stdbit_cast)\n- [std::midpoint](#stdmidpoint)\n- [std::to_array](#stdto_array)\n- [std::bind_front](#stdbind_front)\n- [uniform container erasure](#uniform-container-erasure)\n- [three-way comparison helpers](#three-way-comparison-helpers)\n- [std::lexicographical_compare_three_way](#stdlexicographical_compare_three_way)\n- [std::jthread](#stdjthread)\n- [safe integral comparisons](#safe-integral-comparisons)\n\nC++17 includes the following new language features:\n- [template argument deduction for class templates](#template-argument-deduction-for-class-templates)\n- [declaring non-type template parameters with auto](#declaring-non-type-template-parameters-with-auto)\n- [folding expressions](#folding-expressions)\n- [new rules for auto deduction from braced-init-list](#new-rules-for-auto-deduction-from-braced-init-list)\n- [constexpr lambda](#constexpr-lambda)\n- [lambda capture this by value](#lambda-capture-this-by-value)\n- [inline variables](#inline-variables)\n- [nested namespaces](#nested-namespaces)\n- [structured bindings](#structured-bindings)\n- [selection statements with initializer](#selection-statements-with-initializer)\n- [constexpr if](#constexpr-if)\n- [utf-8 character literals](#utf-8-character-literals)\n- [direct-list-initialization of enums](#direct-list-initialization-of-enums)\n- [\\[\\[fallthrough\\]\\], \\[\\[nodiscard\\]\\], \\[\\[maybe_unused\\]\\] attributes](#fallthrough-nodiscard-maybe_unused-attributes)\n- [\\_\\_has\\_include](#\\_\\_has\\_include)\n- [class template argument deduction](#class-template-argument-deduction)\n\nC++17 includes the following new library features:\n- [std::variant](#stdvariant)\n- [std::optional](#stdoptional)\n- [std::any](#stdany)\n- [std::string_view](#stdstring_view)\n- [std::invoke](#stdinvoke)\n- [std::apply](#stdapply)\n- [std::filesystem](#stdfilesystem)\n- [std::byte](#stdbyte)\n- [splicing for maps and sets](#splicing-for-maps-and-sets)\n- [parallel algorithms](#parallel-algorithms)\n- [std::sample](#stdsample)\n- [std::clamp](#stdclamp)\n- [std::reduce](#stdreduce)\n- [prefix sum algorithms](#prefix-sum-algorithms)\n- [gcd and lcm](#gcd-and-lcm)\n- [std::not_fn](#stdnot_fn)\n- [string conversion to\u002Ffrom numbers](#string-conversion-tofrom-numbers)\n- [rounding functions for chrono durations and timepoints](#rounding-functions-for-chrono-durations-and-timepoints)\n\nC++14 includes the following new language features:\n- [binary literals](#binary-literals)\n- [generic lambda expressions](#generic-lambda-expressions)\n- [lambda capture initializers](#lambda-capture-initializers)\n- [return type deduction](#return-type-deduction)\n- [decltype(auto)](#decltypeauto)\n- [relaxing constraints on constexpr functions](#relaxing-constraints-on-constexpr-functions)\n- [variable templates](#variable-templates)\n- [\\[\\[deprecated\\]\\] attribute](#deprecated-attribute)\n\nC++14 includes the following new library features:\n- [user-defined literals for standard library types](#user-defined-literals-for-standard-library-types)\n- [compile-time integer sequences](#compile-time-integer-sequences)\n- [std::make_unique](#stdmake_unique)\n\nC++11 includes the following new language features:\n- [move semantics](#move-semantics)\n- [variadic templates](#variadic-templates)\n- [rvalue references](#rvalue-references)\n- [forwarding references](#forwarding-references)\n- [initializer lists](#initializer-lists)\n- [static assertions](#static-assertions)\n- [auto](#auto)\n- [lambda expressions](#lambda-expressions)\n- [decltype](#decltype)\n- [type aliases](#type-aliases)\n- [nullptr](#nullptr)\n- [strongly-typed enums](#strongly-typed-enums)\n- [attributes](#attributes)\n- [constexpr](#constexpr)\n- [delegating constructors](#delegating-constructors)\n- [user-defined literals](#user-defined-literals)\n- [explicit virtual overrides](#explicit-virtual-overrides)\n- [final specifier](#final-specifier)\n- [default functions](#default-functions)\n- [deleted functions](#deleted-functions)\n- [range-based for loops](#range-based-for-loops)\n- [special member functions for move semantics](#special-member-functions-for-move-semantics)\n- [converting constructors](#converting-constructors)\n- [explicit conversion functions](#explicit-conversion-functions)\n- [inline-namespaces](#inline-namespaces)\n- [non-static data member initializers](#non-static-data-member-initializers)\n- [right angle brackets](#right-angle-brackets)\n- [ref-qualified member functions](#ref-qualified-member-functions)\n- [trailing return types](#trailing-return-types)\n- [noexcept specifier](#noexcept-specifier)\n- [char32_t and char16_t](#char32_t-and-char16_t)\n- [raw string literals](#raw-string-literals)\n\nC++11 includes the following new library features:\n- [std::move](#stdmove)\n- [std::forward](#stdforward)\n- [std::thread](#stdthread)\n- [std::to_string](#stdto_string)\n- [type traits](#type-traits)\n- [smart pointers](#smart-pointers)\n- [std::chrono](#stdchrono)\n- [tuples](#tuples)\n- [std::tie](#stdtie)\n- [std::array](#stdarray)\n- [unordered containers](#unordered-containers)\n- [std::make_shared](#stdmake_shared)\n- [std::ref](#stdref)\n- [memory model](#memory-model)\n- [std::async](#stdasync)\n- [std::begin\u002Fend](#stdbeginend)\n\n## C++23 Language Features\n\n### consteval if\nWrite code that is instantiated during constant evaluation.\n```c++\nconsteval int f(int i) { return i; }\n\nconstexpr int g(int i) {\n  if consteval {\n      return f(i);\n  } else {\n      return 42;\n  }\n}\n```\n\n### Deducing `this`\nUsing explicit object member functions introduced in C++23, deducing the object's type and value category is now possible by specifying the first parameter of a member function prefixed with the `this` keyword:\n```c++\n\u002F\u002F NEW WAY USING DEDUCING THIS:\nstruct T {\n  decltype(auto) operator[](this auto& self, std::size_t idx) { \n    return self.mVector[idx]; \n  }\n};\n\n\u002F\u002F OLD WAY:\nstruct T {\n  value_t& operator[](std::size_t idx) {\n    return mVector[idx];\n  }\n  const value_t& operator[](std::size_t idx) const {\n    return mVector[idx];\n  }\n};\n```\n\n### Multidimensional subscript operator\nSpecify zero or more arguments to the `operator[]` operator:\n```c++\ntemplate \u003Ctypename T, std::size_t Z, std::size_t Y, std::size_t X>\nstruct Array3d {\n  std::array\u003CT, X * Y * Z> m{};\n\n  T& operator[](std::size_t z, std::size_t y, std::size_t x) {\n      return m[z * Y * X + y * X + x];\n  }\n};\n\nArray3d\u003Cint, 4, 3, 2> v;\nv[3, 2, 1] = 42;\n```\n\n### Increasing range-based `for` safety\nFixes some of the notorious lifetime issues with one of the most important control structures in C++.\n\nSome examples of code snippets that were broken pre-C++23 that are now fixed:\n\n* `for (auto e : getTmp().getRef())`\n* `for (auto e : getVector()[0])`\n* `for (auto valueElem : getMap()[\"key\"])`\n* `for (auto e : get\u003C0>(getTuple()))`\n* `for (auto e : getOptionalCollection().value())`\n* `for (char c : get\u003Cstd::string>(getVariant()))`\n\n## C++23 Library Features\n\n### Stacktrace library\nA stacktrace is an approximate representation of an invocation sequence and consists of stacktrace entries. A stacktrace entry (represented by `std::stacktrace_entry`) consists of information including the source file and line number, and a description field.\n\nExample output on a Linux system:\n```c++\n#include \u003Cprint>\n#include \u003Cstacktrace>\n\nint main() {\n    std::println(\"{}\", std::stacktrace::current());\n}\n```\n```\n  0#  main at \u002Fapp\u002Fexample.cpp:5 [0x5ee42e3db747]\n  1#  \u003Cunknown> [0x76e76dc29d8f]\n  2#  __libc_start_main [0x76e76dc29e3f]\n  3#  _start [0x5ee42e3db644]\n```\n\n### `contains` for strings and string views\nA simpler function for querying if a substring is contained within a string or string view:\n```c++\nstd::string{\"foobarbaz\"}.contains(\"bar\"); \u002F\u002F == true\nstd::string{\"foobarbaz\"}.contains(\"bat\"); \u002F\u002F == false\n```\n\n### `std::to_underlying`\nSupports the common utility of converting an enumeration to its underlying type:\n```c++\nenum class MyEnum : int { A = 1, B, C };\nstd::to_underlying(MyEnum::A); \u002F\u002F == 1\nstd::to_underlying(MyEnum::C); \u002F\u002F == 3\n```\n\n### `spanstream`\nA `strstream` replacement using a character span as an externally-provided buffer. No ownership or re-allocation on the buffer.\n```c++\nchar input[] = \"10 20 30\";\nstd::ispanstream is{std::span\u003Cchar>{input}};\nint i;\nis >> i; \u002F\u002F i == 10\nis >> i; \u002F\u002F i == 20\nis >> i; \u002F\u002F i == 30\n```\n```c++\nchar output[30]{}; \u002F\u002F zero-initialize array\nstd::ospanstream os{std::span\u003Cchar>{output}};\nos \u003C\u003C 10 \u003C\u003C 20 \u003C\u003C 30;\nstd::span\u003Cchar> sp = os.span();\n```\n\n### Input\u002Foutput pointers\n`std::out_ptr` and `std::inout_ptr` are abstractions to support both C APIs and smart pointers by creating a temporary pointer-to-pointer that updates the smart pointer when it destructs. In short: it's a thing convertible to a `T**` that updates (with a `reset` call or semantically equivalent behavior) the smart pointer it is created with when it goes out of scope.\n\nThis abstraction also safely manages the lifetime of the associated memory when exceptions are thrown.\n```c++\n\u002F\u002F p_handle is written (out) to.\nint c_api_create_handle(MyHandle** p_handle);\n\u002F\u002F p_handle is both read (in) and written (out) to.\nint c_api_recreate_handle(MyHandle** p_handle);\nvoid c_api_delete_handle(MyHandle* handle);\n\nstruct resource_deleter {\n\tvoid operator()(MyHandle* handle) {\n\t\tc_api_delete_handle(handle);\n\t}\n};\n```\n```c++\nstd::unique_ptr\u003CMyHandle, resource_deleter> resource(nullptr);\nint err = c_api_create_handle(std::out_ptr(resource));\n\u002F\u002F `resource` now owns the memory allocated within `c_api_create_handle`.\n```\n```c++\nstd::shared_ptr\u003CMyHandle> resource(nullptr);\nint err = c_api_recreate_handle(std::inout_ptr(resource), resource_deleter{});\n\u002F\u002F `resource` now shares the memory allocated within `c_api_recreate_handle`.\n```\n\nBoth inout\u002Fout pointers support casts to `void**` (implicitly), and explicitly to user-specified types.\n\n### Monadic operations for `std::optional`\nSupport various `and_then`, `transform`, and `or_else` operations for `std::optional`.\n```c++\nstd::optional\u003Cint> parse_int(const std::string&);\nstd::optional\u003Cint> ensure_non_negative(int);\nstd::optional\u003Cdouble> default_value_or_empty(double);\n\nstd::optional\u003Cdouble> stringToSqrtDouble(const std::string& input) {\n  return parse_int(input)\n    .and_then(ensure_non_negative)\n    .transform([](int x) {\n      return std::sqrt(x);\n    })\n    .or_else(default_value_or_empty);\n}\n```\n\n### `std::expected`\n`std::expected` provides a way to represent a value and a potential error value, both contained in one type. Also supports a variety of monadic operations on both the expected and unexpected (i.e. error) values.\n\nUse `std::unexpected` to store an unexpected (i.e. error) value.\n```c++\nenum class StringToSqrtDoubleError {\n    ParseError, NegativeNumber\n};\n\nstd::expected\u003Cint, StringToSqrtDoubleError> parse_int(const std::string&);\n\nstd::expected\u003Cdouble, StringToSqrtDoubleError> stringToSqrtDouble(const std::string& input) {\n    auto parsed = parse_int(input);\n    if (!parsed) return parsed;\n\n    auto parsedInt = *parsed;\n    if (parsedInt \u003C 0) return std::unexpected(StringToSqrtDoubleError::NegativeNumber);\n\n    return std::sqrt(parsedInt);\n}\n```\n\n### `std::unreachable`\nProvides a way to explicitly mark a code path as unreachable. May exhibit undefined behavior if the code path is reached.\n```c++\nenum class MyEnum { A, B, C };\n\nint convertMyEnumToInt(MyEnum e) {\n    switch (e) {\n        case MyEnum::A: return 0;\n        case MyEnum::B: return 1;\n        case MyEnum::C: return 2;\n        default: std::unreachable(); \n    }\n}\n```\n\n## C++20 Language Features\n\n### Coroutines\n\n> **Note:** While these examples illustrate how to use coroutines at a basic level, there is lots more going on when the code is compiled. These examples are not meant to be complete coverage of C++20's coroutines. Since the `generator` and `task` classes are not provided by the standard library yet, I used the cppcoro library to compile these examples.\n\n_Coroutines_ are special functions that can have their execution suspended and resumed. To define a coroutine, the `co_return`, `co_await`, or `co_yield` keywords must be present in the function's body. C++20's coroutines are stackless; unless optimized out by the compiler, their state is allocated on the heap.\n\nAn example of a coroutine is a _generator_ function, which yields (i.e. generates) a value at each invocation:\n```c++\ngenerator\u003Cint> range(int start, int end) {\n  while (start \u003C end) {\n    co_yield start;\n    start++;\n  }\n\n  \u002F\u002F Implicit co_return at the end of this function:\n  \u002F\u002F co_return;\n}\n\nfor (int n : range(0, 10)) {\n  std::cout \u003C\u003C n \u003C\u003C std::endl;\n}\n```\nThe above `range` generator function generates values starting at `start` until `end` (exclusive), with each iteration step yielding the current value stored in `start`. The generator maintains its state across each invocation of `range` (in this case, the invocation is for each iteration in the for loop). `co_yield` takes the given expression, yields (i.e. returns) its value, and suspends the coroutine at that point. Upon resuming, execution continues after the `co_yield`.\n\nAnother example of a coroutine is a _task_, which is an asynchronous computation that is executed when the task is awaited:\n```c++\ntask\u003Cvoid> echo(socket s) {\n  for (;;) {\n    auto data = co_await s.async_read();\n    co_await async_write(s, data);\n  }\n\n  \u002F\u002F Implicit co_return at the end of this function:\n  \u002F\u002F co_return;\n}\n```\nIn this example, the `co_await` keyword is introduced. This keyword takes an expression and suspends execution if the thing you're awaiting on (in this case, the read or write) is not ready, otherwise you continue execution. (Note that under the hood, `co_yield` uses `co_await`.)\n\nUsing a task to lazily evaluate a value:\n```c++\ntask\u003Cint> calculate_meaning_of_life() {\n  co_return 42;\n}\n\nauto meaning_of_life = calculate_meaning_of_life();\n\u002F\u002F ...\nco_await meaning_of_life; \u002F\u002F == 42\n```\n\n### Concepts\n_Concepts_ are named compile-time predicates which constrain types. They take the following form:\n```\ntemplate \u003C template-parameter-list >\nconcept concept-name = constraint-expression;\n```\nwhere `constraint-expression` evaluates to a constexpr Boolean. _Constraints_ should model semantic requirements, such as whether a type is a numeric or hashable. A compiler error results if a given type does not satisfy the concept it's bound by (i.e. `constraint-expression` returns `false`). Because constraints are evaluated at compile-time, they can provide more meaningful error messages and runtime safety.\n```c++\n\u002F\u002F `T` is not limited by any constraints.\ntemplate \u003Ctypename T>\nconcept always_satisfied = true;\n\u002F\u002F Limit `T` to integrals.\ntemplate \u003Ctypename T>\nconcept integral = std::is_integral_v\u003CT>;\n\u002F\u002F Limit `T` to both the `integral` constraint and signedness.\ntemplate \u003Ctypename T>\nconcept signed_integral = integral\u003CT> && std::is_signed_v\u003CT>;\n\u002F\u002F Limit `T` to both the `integral` constraint and the negation of the `signed_integral` constraint.\ntemplate \u003Ctypename T>\nconcept unsigned_integral = integral\u003CT> && !signed_integral\u003CT>;\n```\nThere are a variety of syntactic forms for enforcing concepts:\n```c++\n\u002F\u002F Forms for function parameters:\n\u002F\u002F `T` is a constrained type template parameter.\ntemplate \u003Cmy_concept T>\nvoid f(T v);\n\n\u002F\u002F `T` is a constrained type template parameter.\ntemplate \u003Ctypename T>\n  requires my_concept\u003CT>\nvoid f(T v);\n\n\u002F\u002F `T` is a constrained type template parameter.\ntemplate \u003Ctypename T>\nvoid f(T v) requires my_concept\u003CT>;\n\n\u002F\u002F `v` is a constrained deduced parameter.\nvoid f(my_concept auto v);\n\n\u002F\u002F `v` is a constrained non-type template parameter.\ntemplate \u003Cmy_concept auto v>\nvoid g();\n\n\u002F\u002F Forms for auto-deduced variables:\n\u002F\u002F `foo` is a constrained auto-deduced value.\nmy_concept auto foo = ...;\n\n\u002F\u002F Forms for lambdas:\n\u002F\u002F `T` is a constrained type template parameter.\nauto f = []\u003Cmy_concept T> (T v) {\n  \u002F\u002F ...\n};\n\u002F\u002F `T` is a constrained type template parameter.\nauto f = []\u003Ctypename T> requires my_concept\u003CT> (T v) {\n  \u002F\u002F ...\n};\n\u002F\u002F `T` is a constrained type template parameter.\nauto f = []\u003Ctypename T> (T v) requires my_concept\u003CT> {\n  \u002F\u002F ...\n};\n\u002F\u002F `v` is a constrained deduced parameter.\nauto f = [](my_concept auto v) {\n  \u002F\u002F ...\n};\n\u002F\u002F `v` is a constrained non-type template parameter.\nauto g = []\u003Cmy_concept auto v> () {\n  \u002F\u002F ...\n};\n```\nThe `requires` keyword is used either to start a `requires` clause or a `requires` expression:\n```c++\ntemplate \u003Ctypename T>\n  requires my_concept\u003CT> \u002F\u002F `requires` clause.\nvoid f(T);\n\ntemplate \u003Ctypename T>\nconcept callable = requires (T f) { f(); }; \u002F\u002F `requires` expression.\n\ntemplate \u003Ctypename T>\n  requires requires (T x) { x + x; } \u002F\u002F `requires` clause and expression on same line.\nT add(T a, T b) {\n  return a + b;\n}\n```\nNote that the parameter list in a `requires` expression is optional. Each requirement in a `requires` expression are one of the following:\n\n* **Simple requirements** - asserts that the given expression is valid.\n\n```c++\ntemplate \u003Ctypename T>\nconcept callable = requires (T f) { f(); };\n```\n* **Type requirements** - denoted by the `typename` keyword followed by a type name, asserts that the given type name is valid.\n\n```c++\nstruct foo {\n  int foo;\n};\n\nstruct bar {\n  using value = int;\n  value data;\n};\n\nstruct baz {\n  using value = int;\n  value data;\n};\n\n\u002F\u002F Using SFINAE, enable if `T` is a `baz`.\ntemplate \u003Ctypename T, typename = std::enable_if_t\u003Cstd::is_same_v\u003CT, baz>>>\nstruct S {};\n\ntemplate \u003Ctypename T>\nusing Ref = T&;\n\ntemplate \u003Ctypename T>\nconcept C = requires {\n                     \u002F\u002F Requirements on type `T`:\n  typename T::value; \u002F\u002F A) has an inner member named `value`\n  typename S\u003CT>;     \u002F\u002F B) must have a valid class template specialization for `S`\n  typename Ref\u003CT>;   \u002F\u002F C) must be a valid alias template substitution\n};\n\ntemplate \u003CC T>\nvoid g(T a);\n\ng(foo{}); \u002F\u002F ERROR: Fails requirement A.\ng(bar{}); \u002F\u002F ERROR: Fails requirement B.\ng(baz{}); \u002F\u002F PASS.\n```\n* **Compound requirements** - an expression in braces followed by a trailing return type or type constraint.\n\n```c++\ntemplate \u003Ctypename T>\nconcept C = requires(T x) {\n  {*x} -> std::convertible_to\u003Ctypename T::inner>; \u002F\u002F the type of the expression `*x` is convertible to `T::inner`\n  {x + 1} -> std::same_as\u003Cint>; \u002F\u002F the expression `x + 1` satisfies `std::same_as\u003Cdecltype((x + 1))>`\n  {x * 1} -> std::convertible_to\u003CT>; \u002F\u002F the type of the expression `x * 1` is convertible to `T`\n};\n```\n* **Nested requirements** - denoted by the `requires` keyword, specify additional constraints (such as those on local parameter arguments).\n\n```c++\ntemplate \u003Ctypename T>\nconcept C = requires(T x) {\n  requires std::same_as\u003Csizeof(x), size_t>;\n};\n```\nSee also: [concepts library](#concepts-library).\n\n### Three-way comparison\nC++20 introduces the spaceship operator (`\u003C=>`) as a new way to write comparison functions that reduce boilerplate and help developers define clearer comparison semantics. Defining a three-way comparison operator will autogenerate the other comparison operator functions (i.e. `==`, `!=`, `\u003C`, etc.).\n\nThree orderings are introduced:\n* `std::strong_ordering`: The strong ordering distinguishes between items being equal (identical and interchangeable). Provides `less`, `greater`, `equivalent`, and `equal` ordering. Examples of comparisons: searching for a specific value in a list, values of integers, case-sensitive strings.\n* `std::weak_ordering`: The weak ordering distinguishes between items being equivalent (not identical, but can be interchangeable for the purposes of comparison). Provides `less`, `greater`, and `equivalent` ordering. Examples of comparisons: case-insensitive strings, sorting, comparing some but not all visible members of a class.\n* `std::partial_ordering`: The partial ordering follows the same principle of weak ordering but includes the case when an ordering isn't possible. Provides `less`, `greater`, `equivalent`, and `unordered` ordering. Examples of comparisons: floating-point values (e.g. `NaN`).\n\nA defaulted three-way comparison operator does a member-wise comparison:\n```c++\nstruct foo {\n  int a;\n  bool b;\n  char c;\n\n  \u002F\u002F Compare `a` first, then `b`, then `c` ...\n  friend auto operator\u003C=>(const foo&) const = default;\n};\n\nfoo f1{0, false, 'a'}, f2{0, true, 'b'};\nf1 \u003C f2; \u002F\u002F == true\nf1 == f2; \u002F\u002F == false\nf1 >= f2; \u002F\u002F == false\n```\n\nYou can also define your own comparisons:\n```c++\nstruct foo {\n  int x;\n  bool b;\n  char c;\n\n  friend std::strong_ordering operator\u003C=>(const foo& other) const {\n      return x \u003C=> other.x;\n  }\n};\n\nfoo f1{0, false, 'a'}, f2{0, true, 'b'};\nf1 \u003C f2; \u002F\u002F == false\nf1 == f2; \u002F\u002F == true\nf1 >= f2; \u002F\u002F == true\n```\n\n### Designated initializers\nC-style designated initializer syntax. Any member fields that are not explicitly listed in the designated initializer list are default-initialized.\n```c++\nstruct A {\n  int x;\n  int y;\n  int z = 123;\n};\n\nA a {.x = 1, .z = 2}; \u002F\u002F a.x == 1, a.y == 0, a.z == 2\n```\n\n### Template syntax for lambdas\nUse familiar template syntax in lambda expressions.\n```c++\nauto f = []\u003Ctypename T>(std::vector\u003CT> v) {\n  \u002F\u002F ...\n};\n```\n\n### Range-based for loop with initializer\nThis feature simplifies common code patterns, helps keep scopes tight, and offers an elegant solution to a common lifetime problem.\n```c++\nfor (auto v = std::vector{1, 2, 3}; auto& e : v) {\n  std::cout \u003C\u003C e;\n}\n\u002F\u002F prints \"123\"\n```\n\n### \\[\\[likely\\]\\] and \\[\\[unlikely\\]\\] attributes\nProvides a hint to the optimizer that the labelled statement has a high probability of being executed.\n```c++\nswitch (n) {\ncase 1:\n  \u002F\u002F ...\n  break;\n\n[[likely]] case 2:  \u002F\u002F n == 2 is considered to be arbitrarily more\n  \u002F\u002F ...            \u002F\u002F likely than any other value of n\n  break;\n}\n```\n\nIf one of the likely\u002Funlikely attributes appears after the right parenthesis of an if-statement,\nit indicates that the branch is likely\u002Funlikely to have its substatement (body) executed.\n```c++\nint random = get_random_number_between_x_and_y(0, 3);\nif (random > 0) [[likely]] {\n  \u002F\u002F body of if statement\n  \u002F\u002F ...\n}\n```\n\nIt can also be applied to the substatement (body) of an iteration statement.\n```c++\nwhile (unlikely_truthy_condition) [[unlikely]] {\n  \u002F\u002F body of while statement\n  \u002F\u002F ...\n}\n```\n\n### Deprecate implicit capture of this\nImplicitly capturing `this` in a lambda capture using `[=]` is now deprecated; prefer capturing explicitly using `[=, this]` or `[=, *this]`.\n```c++\nstruct int_value {\n  int n = 0;\n  auto getter_fn() {\n    \u002F\u002F BAD:\n    \u002F\u002F return [=]() { return n; };\n\n    \u002F\u002F GOOD:\n    return [=, *this]() { return n; };\n  }\n};\n```\n\n### Class types in non-type template parameters\nClasses can now be used in non-type template parameters. Objects passed in as template arguments have the type `const T`, where `T` is the type of the object, and has static storage duration.\n```c++\nstruct foo {\n  foo() = default;\n  constexpr foo(int) {}\n};\n\ntemplate \u003Cfoo f = {}>\nauto get_foo() {\n  return f;\n}\n\nget_foo(); \u002F\u002F uses implicit constructor\nget_foo\u003Cfoo{123}>();\n```\n\n### constexpr virtual functions\nVirtual functions can now be `constexpr` and evaluated at compile-time. `constexpr` virtual functions can override non-`constexpr` virtual functions and vice-versa.\n```c++\nstruct X1 {\n  virtual int f() const = 0;\n};\n\nstruct X2: public X1 {\n  constexpr virtual int f() const { return 2; }\n};\n\nstruct X3: public X2 {\n  virtual int f() const { return 3; }\n};\n\nstruct X4: public X3 {\n  constexpr virtual int f() const { return 4; }\n};\n\nconstexpr X4 x4;\nx4.f(); \u002F\u002F == 4\n```\n\n### explicit(bool)\nConditionally select at compile-time whether a constructor is made explicit or not. `explicit(true)` is the same as specifying `explicit`.\n```c++\nstruct foo {\n  \u002F\u002F Specify non-integral types (strings, floats, etc.) require explicit construction.\n  template \u003Ctypename T>\n  explicit(!std::is_integral_v\u003CT>) foo(T) {}\n};\n\nfoo a = 123; \u002F\u002F OK\nfoo b = \"123\"; \u002F\u002F ERROR: explicit constructor is not a candidate (explicit specifier evaluates to true)\nfoo c {\"123\"}; \u002F\u002F OK\n```\n\n### Immediate functions\nSimilar to `constexpr` functions, but functions with a `consteval` specifier must produce a constant. These are called `immediate functions`.\n```c++\nconsteval int sqr(int n) {\n  return n * n;\n}\n\nconstexpr int r = sqr(100); \u002F\u002F OK\nint x = 100;\nint r2 = sqr(x); \u002F\u002F ERROR: the value of 'x' is not usable in a constant expression\n                 \u002F\u002F OK if `sqr` were a `constexpr` function\n```\n\n### using enum\nBring an enum's members into scope to improve readability. Before:\n```c++\nenum class rgba_color_channel { red, green, blue, alpha };\n\nstd::string_view to_string(rgba_color_channel channel) {\n  switch (channel) {\n    case rgba_color_channel::red:   return \"red\";\n    case rgba_color_channel::green: return \"green\";\n    case rgba_color_channel::blue:  return \"blue\";\n    case rgba_color_channel::alpha: return \"alpha\";\n  }\n}\n```\nAfter:\n```c++\nenum class rgba_color_channel { red, green, blue, alpha };\n\nstd::string_view to_string(rgba_color_channel my_channel) {\n  switch (my_channel) {\n    using enum rgba_color_channel;\n    case red:   return \"red\";\n    case green: return \"green\";\n    case blue:  return \"blue\";\n    case alpha: return \"alpha\";\n  }\n}\n```\n\n### Lambda capture of parameter pack\nCapture parameter packs by value:\n```c++\ntemplate \u003Ctypename... Args>\nauto f(Args&&... args){\n    \u002F\u002F BY VALUE:\n    return [...args = std::forward\u003CArgs>(args)] {\n        \u002F\u002F ...\n    };\n}\n```\nCapture parameter packs by reference:\n```c++\ntemplate \u003Ctypename... Args>\nauto f(Args&&... args){\n    \u002F\u002F BY REFERENCE:\n    return [&...args = std::forward\u003CArgs>(args)] {\n        \u002F\u002F ...\n    };\n}\n```\n\n### char8_t\nProvides a standard type for representing UTF-8 strings.\n```c++\nchar8_t utf8_str[] = u8\"\\u0123\";\n```\n\n### constinit\nThe `constinit` specifier requires that a variable must be initialized at compile-time.\n```c++\nconst char* g() { return \"dynamic initialization\"; }\nconstexpr const char* f() { return \"constant initializer\"; }\n\nconstinit const char* c = f();  \u002F\u002F OK\nconstinit const char* d = g();  \u002F\u002F ERROR: `g` is not constexpr, so `d` cannot be evaluated at compile-time.\n```\n\n### \\_\\_VA\\_OPT\\_\\_\nHelps support variadic macros by evaluating to the given argument if the variadic macro is non-empty.\n```c++\n#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)\nF(a, b, c) \u002F\u002F replaced by f(0, a, b, c)\nF()        \u002F\u002F replaced by f(0)\n```\n\n## C++20 Library Features\n\n### Text formatting\nProvides a compile-time, checked string formatting library to the standard library using `std::format`. Text formatting can also be done at runtime for dynamic formatted strings using `std::vformat` and other help utilities. Text formatting follows the given [specification](https:\u002F\u002Fen.cppreference.com\u002Fw\u002Fcpp\u002Futility\u002Fformat\u002Fspec.html).\n\n`std::format` receives a format string as the first argument, and a variable number of arguments proceeding it. If formatting fails, the compilation will fail:\n\n```cpp\nstd::format(\"{}\", 123); \u002F\u002F OK -- returns \"123\"\nstd::format(\"{} {}\", 123); \u002F\u002F ERROR -- not enough arguments\nstd::format(\"{} {}\", \"Here's a number:\", 123); \u002F\u002F OK\n```\n\nFormatting a string based on a formatter created at runtime:\n\n```cpp\nstd::string fmt = \"{} {}\";\nfmt += \"{}{}\";\nstd::vformat(fmt, std::make_format_args(\"Here's a number:\", 1, 2, 3));\n\u002F\u002F OK -- returns \"Here's a number: 123\"\n```\n\nWhen formatting fails (such as an invalid format string), `std::vformat` will throw a `std::format_error`.\n\nTo format custom types:\n\n```c++\nstruct fraction {\n  int numerator;\n  int denominator;\n};\n\ntemplate \u003C>\nstruct std::formatter\u003Cfraction> {\n  constexpr auto parse(std::format_parse_context& ctx) {\n    return ctx.begin();\n  }\n\n  auto format(const fraction& f, std::format_context& ctx) const {\n    return std::format_to(ctx.out(), \"{0:d}\u002F{1:d}\", f.numerator, f.denominator);\n  }\n};\n\nfraction f{1, 2};\nstd::format(\"{}\", f); \u002F\u002F == \"1\u002F2\"\n```\n\n### Concepts library\nConcepts are also provided by the standard library for building more complicated concepts. Some of these include:\n\n**Core language concepts:**\n- `same_as` - specifies two types are the same.\n- `derived_from` - specifies that a type is derived from another type.\n- `convertible_to` - specifies that a type is implicitly convertible to another type.\n- `common_with` - specifies that two types share a common type.\n- `integral` - specifies that a type is an integral type.\n- `default_constructible` - specifies that an object of a type can be default-constructed.\n\n **Comparison concepts:**\n- `boolean` - specifies that a type can be used in Boolean contexts.\n- `equality_comparable` - specifies that `operator==` is an equivalence relation.\n\n **Object concepts:**\n- `movable` - specifies that an object of a type can be moved and swapped.\n- `copyable` - specifies that an object of a type can be copied, moved, and swapped.\n- `semiregular` - specifies that an object of a type can be copied, moved, swapped, and default constructed.\n- `regular` - specifies that a type is _regular_, that is, it is both `semiregular` and `equality_comparable`.\n\n **Callable concepts:**\n- `invocable` - specifies that a callable type can be invoked with a given set of argument types.\n- `predicate` - specifies that a callable type is a Boolean predicate.\n\nSee also: [concepts](#concepts).\n\n### Synchronized buffered outputstream\nBuffers output operations for the wrapped output stream ensuring synchronization (i.e. no interleaving of output).\n```c++\nstd::osyncstream{std::cout} \u003C\u003C \"The value of x is:\" \u003C\u003C x \u003C\u003C std::endl;\n```\n\n### std::span\nA span is a view (i.e. non-owning) of a container providing bounds-checked access to a contiguous group of elements. Since views do not own their elements they are cheap to construct and copy -- a simplified way to think about views is they are holding references to their data. As opposed to maintaining a pointer\u002Fiterator and length field, a span wraps both of those up in a single object.\n\nSpans can be dynamically-sized or fixed-sized (known as their *extent*). Fixed-sized spans benefit from bounds-checking.\n\nSpan doesn't propogate const so to construct a read-only span use `std::span\u003Cconst T>`.\n\nExample: using a dynamically-sized span to print integers from various containers.\n```c++\nvoid print_ints(std::span\u003Cconst int> ints) {\n    for (const auto n : ints) {\n        std::cout \u003C\u003C n \u003C\u003C std::endl;\n    }\n}\n\nprint_ints(std::vector{ 1, 2, 3 });\nprint_ints(std::array\u003Cint, 5>{ 1, 2, 3, 4, 5 });\n\nint a[10] = { 0 };\nprint_ints(a);\n\u002F\u002F etc.\n```\n\nExample: a statically-sized span will fail to compile for containers that don't match the extent of the span.\n```c++\nvoid print_three_ints(std::span\u003Cconst int, 3> ints) {\n    for (const auto n : ints) {\n        std::cout \u003C\u003C n \u003C\u003C std::endl;\n    }\n}\n\nprint_three_ints(std::vector{ 1, 2, 3 }); \u002F\u002F ERROR\nprint_three_ints(std::array\u003Cint, 5>{ 1, 2, 3, 4, 5 }); \u002F\u002F ERROR\nint a[10] = { 0 };\nprint_three_ints(a); \u002F\u002F ERROR\n\nstd::array\u003Cint, 3> b = { 1, 2, 3 };\nprint_three_ints(b); \u002F\u002F OK\n\n\u002F\u002F You can construct a span manually if required:\nstd::vector c{ 1, 2, 3 };\nprint_three_ints(std::span\u003Cconst int, 3>{ c.data(), 3 }); \u002F\u002F OK: set pointer and length field.\nprint_three_ints(std::span\u003Cconst int, 3>{ c.cbegin(), c.cend() }); \u002F\u002F OK: use iterator pairs.\n```\n\n### Bit operations\nC++20 provides a new `\u003Cbit>` header which provides some bit operations including popcount.\n```c++\nstd::popcount(0u); \u002F\u002F 0\nstd::popcount(1u); \u002F\u002F 1\nstd::popcount(0b1111'0000u); \u002F\u002F 4\n```\n\n### Math constants\nMathematical constants including PI, Euler's number, etc. defined in the `\u003Cnumbers>` header.\n```c++\nstd::numbers::pi; \u002F\u002F 3.14159...\nstd::numbers::e; \u002F\u002F 2.71828...\n```\n\n### std::is_constant_evaluated\nPredicate function which is truthy when it is called in a compile-time context.\n```c++\nconstexpr bool is_compile_time() {\n    return std::is_constant_evaluated();\n}\n\nconstexpr bool a = is_compile_time(); \u002F\u002F true\nbool b = is_compile_time(); \u002F\u002F false\n```\n\n### std::make_shared supports arrays\n```c++\nauto p = std::make_shared\u003Cint[]>(5); \u002F\u002F pointer to `int[5]`\n\u002F\u002F OR\nauto p = std::make_shared\u003Cint[5]>(); \u002F\u002F pointer to `int[5]`\n```\n\n### starts_with and ends_with on strings\nStrings (and string views) now have the `starts_with` and `ends_with` member functions to check if a string starts or ends with the given string.\n```c++\nstd::string str = \"foobar\";\nstr.starts_with(\"foo\"); \u002F\u002F true\nstr.ends_with(\"baz\"); \u002F\u002F false\n```\n\n### Check if associative container has element\nAssociative containers such as sets and maps have a `contains` member function, which can be used instead of the \"find and check end of iterator\" idiom.\n```c++\nstd::map\u003Cint, char> map {{1, 'a'}, {2, 'b'}};\nmap.contains(2); \u002F\u002F true\nmap.contains(123); \u002F\u002F false\n\nstd::set\u003Cint> set {1, 2, 3};\nset.contains(2); \u002F\u002F true\n```\n\n### std::bit_cast\nA safer way to reinterpret an object from one type to another.\n```c++\nfloat f = 123.0;\nint i = std::bit_cast\u003Cint>(f);\n```\n\n### std::midpoint\nCalculate the midpoint of two integers safely (without overflow).\n```c++\nstd::midpoint(1, 3); \u002F\u002F == 2\n```\n\n### std::to_array\nConverts the given array\u002F\"array-like\" object to a `std::array`.\n```c++\nstd::to_array(\"foo\"); \u002F\u002F returns `std::array\u003Cchar, 4>`\nstd::to_array\u003Cint>({1, 2, 3}); \u002F\u002F returns `std::array\u003Cint, 3>`\n\nint a[] = {1, 2, 3};\nstd::to_array(a); \u002F\u002F returns `std::array\u003Cint, 3>`\n```\n\n### std::bind_front\nBinds the first N arguments (where N is the number of arguments after the given function to `std::bind_front`) to a given free function, lambda, or member function.\n```c++\nconst auto f = [](int a, int b, int c) { return a + b + c; };\nconst auto g = std::bind_front(f, 1, 1);\ng(1); \u002F\u002F == 3\n```\n\n### Uniform container erasure\nProvides `std::erase` and\u002For `std::erase_if` for a variety of STL containers such as string, list, vector, map, etc.\n\nFor erasing by value use `std::erase`, or to specify a predicate when to erase elements use `std::erase_if`. Both functions return the number of erased elements.\n\n```c++\nstd::vector v{0, 1, 0, 2, 0, 3};\nstd::erase(v, 0); \u002F\u002F v == {1, 2, 3}\nstd::erase_if(v, [](int n) { return n == 0; }); \u002F\u002F v == {1, 2, 3}\n```\n\n### Three-way comparison helpers\nHelper functions for giving names to comparison results:\n```c++\nstd::is_eq(0 \u003C=> 0); \u002F\u002F == true\nstd::is_lteq(0 \u003C=> 1); \u002F\u002F == true\nstd::is_gt(0 \u003C=> 1); \u002F\u002F == false\n```\n\nSee also: [three-way comparison](#three-way-comparison).\n\n### std::lexicographical_compare_three_way\nLexicographically compares two ranges using three-way comparison and produces a result of the strongest applicable comparison category type.\n```c++\nstd::vector a{0, 0, 0}, b{0, 0, 0}, c{1, 1, 1};\n\nauto cmp_ab = std::lexicographical_compare_three_way(\n    a.begin(), a.end(), b.begin(), b.end());\nstd::is_eq(cmp_ab); \u002F\u002F == true\n\nauto cmp_ac = std::lexicographical_compare_three_way(\n    a.begin(), a.end(), c.begin(), c.end());\nstd::is_lt(cmp_ac); \u002F\u002F == true\n```\n\nSee also: [three-way comparison](#three-way-comparison), [three-way comparison helpers](#three-way-comparison-helpers).\n\n### std::jthread\nA thread of execution (like `std::thread`) that joins on destruction and can be signaled to stop.\n\nAs opposed to `std::thread` where you need to check if a thread is joinable and then join on it, a `std::jthread` will automatically attempt to join through its destructor.\n\nUnlike `std::thread` you can request it stop by calling `std::jthread::request_stop` or through the thread's `stop_source`:\n\n```cpp\nstd::jthread t{\n    [](std::stop_token stoken) {\n        while (!stoken.stop_requested()) {\n            std::this_thread::sleep_for(1s);\n        }\n    }\n};\n\n\u002F\u002F Request stop from the thread object:\nt.request_stop();\n\u002F\u002F OR, through the stop source:\nstd::stop_source stopSource = t.get_stop_source();\nstopSource.request_stop();\n```\n\nA `std::stop_token` can be used to query the stop state of a thread.\n\n### Safe integral comparisons\nCompare integers, including those of distinct types, without the dangers of integer conversion.\n\n```cpp\n-1 > 0U; \u002F\u002F == true\nstd::cmp_greater(-1, 0U); \u002F\u002F == false\n\nstd::cmp_equal(0U, 0); \u002F\u002F == true\nstd::cmp_less_equal(-1, 1U); \u002F\u002F == true\n\nstd::in_range\u003Cunsigned>(-1); \u002F\u002F == false\nstd::in_range\u003Cchar>(999999); \u002F\u002F == false\n```\n\n## C++17 Language Features\n\n### Template argument deduction for class templates\nAutomatic template argument deduction much like how it's done for functions, but now including class constructors.\n```c++\ntemplate \u003Ctypename T = float>\nstruct MyContainer {\n  T val;\n  MyContainer() : val{} {}\n  MyContainer(T val) : val{val} {}\n  \u002F\u002F ...\n};\nMyContainer c1 {1}; \u002F\u002F OK MyContainer\u003Cint>\nMyContainer c2; \u002F\u002F OK MyContainer\u003Cfloat>\n```\n\n### Declaring non-type template parameters with auto\nFollowing the deduction rules of `auto`, while respecting the non-type template parameter list of allowable types[\\*], template arguments can be deduced from the types of its arguments:\n```c++\ntemplate \u003Cauto... seq>\nstruct my_integer_sequence {\n  \u002F\u002F Implementation here ...\n};\n\n\u002F\u002F Explicitly pass type `int` as template argument.\nauto seq = std::integer_sequence\u003Cint, 0, 1, 2>();\n\u002F\u002F Type is deduced to be `int`.\nauto seq2 = my_integer_sequence\u003C0, 1, 2>();\n```\n\\* - For example, you cannot use a `double` as a template parameter type, which also makes this an invalid deduction using `auto`.\n\n### Folding expressions\nA fold expression performs a fold of a template parameter pack over a binary operator.\n* An expression of the form `(... op e)` or `(e op ...)`, where `op` is a fold-operator and `e` is an unexpanded parameter pack, are called _unary folds_.\n* An expression of the form `(e1 op ... op e2)`, where `op` are fold-operators, is called a _binary fold_. Either `e1` or `e2` is an unexpanded parameter pack, but not both.\n```c++\ntemplate \u003Ctypename... Args>\nbool logicalAnd(Args... args) {\n    \u002F\u002F Binary folding.\n    return (true && ... && args);\n}\nbool b = true;\nbool& b2 = b;\nlogicalAnd(b, b2, true); \u002F\u002F == true\n```\n```c++\ntemplate \u003Ctypename... Args>\nauto sum(Args... args) {\n    \u002F\u002F Unary folding.\n    return (... + args);\n}\nsum(1.0, 2.0f, 3); \u002F\u002F == 6.0\n```\n\n### New rules for auto deduction from braced-init-list\nChanges to `auto` deduction when used with the uniform initialization syntax. Previously, `auto x {3};` deduces a `std::initializer_list\u003Cint>`, which now deduces to `int`.\n```c++\nauto x1 {1, 2, 3}; \u002F\u002F error: not a single element\nauto x2 = {1, 2, 3}; \u002F\u002F x2 is std::initializer_list\u003Cint>\nauto x3 {3}; \u002F\u002F x3 is int\nauto x4 {3.0}; \u002F\u002F x4 is double\n```\n\n### constexpr lambda\nCompile-time lambdas using `constexpr`.\n```c++\nauto identity = [](int n) constexpr { return n; };\nstatic_assert(identity(123) == 123);\n```\n```c++\nconstexpr auto add = [](int x, int y) {\n  auto L = [=] { return x; };\n  auto R = [=] { return y; };\n  return [=] { return L() + R(); };\n};\n\nstatic_assert(add(1, 2)() == 3);\n```\n```c++\nconstexpr int addOne(int n) {\n  return [n] { return n + 1; }();\n}\n\nstatic_assert(addOne(1) == 2);\n```\n\n### Lambda capture `this` by value\nCapturing `this` in a lambda's environment was previously reference-only. An example of where this is problematic is asynchronous code using callbacks that require an object to be available, potentially past its lifetime. `*this` (C++17) will now make a copy of the current object, while `this` (C++11) continues to capture by reference.\n```c++\nstruct MyObj {\n  int value {123};\n  auto getValueCopy() {\n    return [*this] { return value; };\n  }\n  auto getValueRef() {\n    return [this] { return value; };\n  }\n};\nMyObj mo;\nauto valueCopy = mo.getValueCopy();\nauto valueRef = mo.getValueRef();\nmo.value = 321;\nvalueCopy(); \u002F\u002F 123\nvalueRef(); \u002F\u002F 321\n```\n\n### Inline variables\nThe inline specifier can be applied to variables as well as to functions. A variable declared inline has the same semantics as a function declared inline.\n```c++\n\u002F\u002F Disassembly example using compiler explorer.\nstruct S { int x; };\ninline S x1 = S{321}; \u002F\u002F mov esi, dword ptr [x1]\n                      \u002F\u002F x1: .long 321\n\nS x2 = S{123};        \u002F\u002F mov eax, dword ptr [.L_ZZ4mainE2x2]\n                      \u002F\u002F mov dword ptr [rbp - 8], eax\n                      \u002F\u002F .L_ZZ4mainE2x2: .long 123\n```\n\nIt can also be used to declare and define a static member variable, such that it does not need to be initialized in the source file.\n```c++\nstruct S {\n  S() : id{count++} {}\n  ~S() { count--; }\n  int id;\n  static inline int count{0}; \u002F\u002F declare and initialize count to 0 within the class\n};\n```\n\n### Nested namespaces\nUsing the namespace resolution operator to create nested namespace definitions.\n```c++\nnamespace A {\n  namespace B {\n    namespace C {\n      int i;\n    }\n  }\n}\n```\n\nThe code above can be written like this:\n```c++\nnamespace A::B::C {\n  int i;\n}\n```\n\n### Structured bindings\nA proposal for de-structuring initialization, that would allow writing `auto [ x, y, z ] = expr;` where the type of `expr` was a tuple-like object, whose elements would be bound to the variables `x`, `y`, and `z` (which this construct declares). _Tuple-like objects_ include [`std::tuple`](#tuples), `std::pair`, [`std::array`](#stdarray), and aggregate structures.\n```c++\nusing Coordinate = std::pair\u003Cint, int>;\nCoordinate origin() {\n  return Coordinate{0, 0};\n}\n\nconst auto [ x, y ] = origin();\nx; \u002F\u002F == 0\ny; \u002F\u002F == 0\n```\n```c++\nstd::unordered_map\u003Cstd::string, int> mapping {\n  {\"a\", 1},\n  {\"b\", 2},\n  {\"c\", 3}\n};\n\n\u002F\u002F Destructure by reference.\nfor (const auto& [key, value] : mapping) {\n  \u002F\u002F Do something with key and value\n}\n```\n\n### Selection statements with initializer\nNew versions of the `if` and `switch` statements which simplify common code patterns and help users keep scopes tight.\n```c++\n{\n  std::lock_guard\u003Cstd::mutex> lk(mx);\n  if (v.empty()) v.push_back(val);\n}\n\u002F\u002F vs.\nif (std::lock_guard\u003Cstd::mutex> lk(mx); v.empty()) {\n  v.push_back(val);\n}\n```\n```c++\nFoo gadget(args);\nswitch (auto s = gadget.status()) {\n  case OK: gadget.zip(); break;\n  case Bad: throw BadFoo(s.message());\n}\n\u002F\u002F vs.\nswitch (Foo gadget(args); auto s = gadget.status()) {\n  case OK: gadget.zip(); break;\n  case Bad: throw BadFoo(s.message());\n}\n```\n\n### constexpr if\nWrite code that is instantiated depending on a compile-time condition.\n```c++\ntemplate \u003Ctypename T>\nconstexpr bool isIntegral() {\n  if constexpr (std::is_integral\u003CT>::value) {\n    return true;\n  } else {\n    return false;\n  }\n}\nstatic_assert(isIntegral\u003Cint>() == true);\nstatic_assert(isIntegral\u003Cchar>() == true);\nstatic_assert(isIntegral\u003Cdouble>() == false);\nstruct S {};\nstatic_assert(isIntegral\u003CS>() == false);\n```\n\n### UTF-8 character literals\nA character literal that begins with `u8` is a character literal of type `char`. The value of a UTF-8 character literal is equal to its ISO 10646 code point value.\n```c++\nchar x = u8'x';\n```\n\n### Direct list initialization of enums\nEnums can now be initialized using braced syntax.\n```c++\nenum byte : unsigned char {};\nbyte b {0}; \u002F\u002F OK\nbyte c {-1}; \u002F\u002F ERROR\nbyte d = byte{1}; \u002F\u002F OK\nbyte e = byte{256}; \u002F\u002F ERROR\n```\n\n### \\[\\[fallthrough\\]\\], \\[\\[nodiscard\\]\\], \\[\\[maybe_unused\\]\\] attributes\nC++17 introduces three new attributes: `[[fallthrough]]`, `[[nodiscard]]` and `[[maybe_unused]]`.\n* `[[fallthrough]]` indicates to the compiler that falling through in a switch statement is intended behavior. This attribute may only be used in a switch statement, and must be placed before the next case\u002Fdefault label.\n```c++\nswitch (n) {\n  case 1: \n    \u002F\u002F ...\n    [[fallthrough]];\n  case 2:\n    \u002F\u002F ...\n    break;\n  case 3:\n    \u002F\u002F ...\n    [[fallthrough]];\n  default:\n    \u002F\u002F ...\n}\n```\n\n* `[[nodiscard]]` issues a warning when either a function or class has this attribute and its return value is discarded.\n```c++\n[[nodiscard]] bool do_something() {\n  return is_success; \u002F\u002F true for success, false for failure\n}\n\ndo_something(); \u002F\u002F warning: ignoring return value of 'bool do_something()',\n                \u002F\u002F declared with attribute 'nodiscard'\n```\n```c++\n\u002F\u002F Only issues a warning when `error_info` is returned by value.\nstruct [[nodiscard]] error_info {\n  \u002F\u002F ...\n};\n\nerror_info do_something() {\n  error_info ei;\n  \u002F\u002F ...\n  return ei;\n}\n\ndo_something(); \u002F\u002F warning: ignoring returned value of type 'error_info',\n                \u002F\u002F declared with attribute 'nodiscard'\n```\n\n* `[[maybe_unused]]` indicates to the compiler that a variable or parameter might be unused and is intended.\n```c++\nvoid my_callback(std::string msg, [[maybe_unused]] bool error) {\n  \u002F\u002F Don't care if `msg` is an error message, just log it.\n  log(msg);\n}\n```\n\n### \\_\\_has\\_include\n\n`__has_include (operand)` operator may be used in `#if` and `#elif` expressions to check whether a header or source file (`operand`) is available for inclusion or not.\n\nOne use case of this would be using two libraries that work the same way, using the backup\u002Fexperimental one if the preferred one is not found on the system.\n\n```c++\n#ifdef __has_include\n#  if __has_include(\u003Coptional>)\n#    include \u003Coptional>\n#    define have_optional 1\n#  elif __has_include(\u003Cexperimental\u002Foptional>)\n#    include \u003Cexperimental\u002Foptional>\n#    define have_optional 1\n#    define experimental_optional\n#  else\n#    define have_optional 0\n#  endif\n#endif\n```\n\nIt can also be used to include headers existing under different names or locations on various platforms, without knowing which platform the program is running on, OpenGL headers are a good example for this which are located in `OpenGL\\` directory on macOS and `GL\\` on other platforms.\n\n```c++\n#ifdef __has_include\n#  if __has_include(\u003COpenGL\u002Fgl.h>)\n#    include \u003COpenGL\u002Fgl.h>\n#    include \u003COpenGL\u002Fglu.h>\n#  elif __has_include(\u003CGL\u002Fgl.h>)\n#    include \u003CGL\u002Fgl.h>\n#    include \u003CGL\u002Fglu.h>\n#  else\n#    error No suitable OpenGL headers found.\n# endif\n#endif\n```\n\n### Class template argument deduction\n*Class template argument deduction* (CTAD) allows the compiler to deduce template arguments from constructor arguments.\n```c++\nstd::vector v{ 1, 2, 3 }; \u002F\u002F deduces std::vector\u003Cint>\n\nstd::mutex mtx;\nauto lck = std::lock_guard{ mtx }; \u002F\u002F deduces to std::lock_guard\u003Cstd::mutex>\n\nauto p = new std::pair{ 1.0, 2.0 }; \u002F\u002F deduces to std::pair\u003Cdouble, double>*\n```\n\nFor user-defined types, *deduction guides* can be used to guide the compiler how to deduce template arguments if applicable:\n```c++\ntemplate \u003Ctypename T>\nstruct container {\n  container(T t) {}\n\n  template \u003Ctypename Iter>\n  container(Iter beg, Iter end);\n};\n\n\u002F\u002F deduction guide\ntemplate \u003Ctypename Iter>\ncontainer(Iter b, Iter e) -> container\u003Ctypename std::iterator_traits\u003CIter>::value_type>;\n\ncontainer a{ 7 }; \u002F\u002F OK: deduces container\u003Cint>\n\nstd::vector\u003Cdouble> v{ 1.0, 2.0, 3.0 };\nauto b = container{ v.begin(), v.end() }; \u002F\u002F OK: deduces container\u003Cdouble>\n\ncontainer c{ 5, 6 }; \u002F\u002F ERROR: std::iterator_traits\u003Cint>::value_type is not a type\n```\n\n## C++17 Library Features\n\n### std::variant\nThe class template `std::variant` represents a type-safe `union`. An instance of `std::variant` at any given time holds a value of one of its alternative types (it's also possible for it to be valueless).\n```c++\nstd::variant\u003Cint, double> v{ 12 };\nstd::get\u003Cint>(v); \u002F\u002F == 12\nstd::get\u003C0>(v); \u002F\u002F == 12\nv = 12.0;\nstd::get\u003Cdouble>(v); \u002F\u002F == 12.0\nstd::get\u003C1>(v); \u002F\u002F == 12.0\n```\n\n### std::optional\nThe class template `std::optional` manages an optional contained value, i.e. a value that may or may not be present. A common use case for optional is the return value of a function that may fail.\n```c++\nstd::optional\u003Cstd::string> create(bool b) {\n  if (b) {\n    return \"Godzilla\";\n  } else {\n    return {};\n  }\n}\n\ncreate(false).value_or(\"empty\"); \u002F\u002F == \"empty\"\ncreate(true).value(); \u002F\u002F == \"Godzilla\"\n\u002F\u002F optional-returning factory functions are usable as conditions of while and if\nif (auto str = create(true)) {\n  \u002F\u002F ...\n}\n```\n\n### std::any\nA type-safe container for single values of any type.\n```c++\nstd::any x {5};\nx.has_value() \u002F\u002F == true\nstd::any_cast\u003Cint>(x) \u002F\u002F == 5\nstd::any_cast\u003Cint&>(x) = 10;\nstd::any_cast\u003Cint>(x) \u002F\u002F == 10\n```\n\n### std::string_view\nA non-owning reference to a string. Useful for providing an abstraction on top of strings (e.g. for parsing).\n```c++\n\u002F\u002F Regular strings.\nstd::string_view cppstr {\"foo\"};\n\u002F\u002F Wide strings.\nstd::wstring_view wcstr_v {L\"baz\"};\n\u002F\u002F Character arrays.\nchar array[3] = {'b', 'a', 'r'};\nstd::string_view array_v(array, std::size(array));\n```\n```c++\nstd::string str {\"   trim me\"};\nstd::string_view v {str};\nv.remove_prefix(std::min(v.find_first_not_of(\" \"), v.size()));\nstr; \u002F\u002F  == \"   trim me\"\nv; \u002F\u002F == \"trim me\"\n```\n\n### std::invoke\nInvoke a `Callable` object with parameters. Examples of *callable* objects are `std::function` or lambdas; objects that can be called similarly to a regular function.\n```c++\ntemplate \u003Ctypename Callable>\nclass Proxy {\n  Callable c_;\n\npublic:\n  Proxy(Callable c) : c_{ std::move(c) } {}\n\n  template \u003Ctypename... Args>\n  decltype(auto) operator()(Args&&... args) {\n    \u002F\u002F ...\n    return std::invoke(c_, std::forward\u003CArgs>(args)...);\n  }\n};\n\nconst auto add = [](int x, int y) { return x + y; };\nProxy p{ add };\np(1, 2); \u002F\u002F == 3\n```\n\n### std::apply\nInvoke a `Callable` object with a tuple of arguments.\n```c++\nauto add = [](int x, int y) {\n  return x + y;\n};\nstd::apply(add, std::make_tuple(1, 2)); \u002F\u002F == 3\n```\n\n### std::filesystem\nThe new `std::filesystem` library provides a standard way to manipulate files, directories, and paths in a filesystem.\n\nHere, a big file is copied to a temporary path if there is available space:\n```c++\nconst auto bigFilePath {\"bigFileToCopy\"};\nif (std::filesystem::exists(bigFilePath)) {\n  const auto bigFileSize {std::filesystem::file_size(bigFilePath)};\n  std::filesystem::path tmpPath {\"\u002Ftmp\"};\n  if (std::filesystem::space(tmpPath).available > bigFileSize) {\n    std::filesystem::create_directory(tmpPath.append(\"example\"));\n    std::filesystem::copy_file(bigFilePath, tmpPath.append(\"newFile\"));\n  }\n}\n```\n\n### std::byte\nThe new `std::byte` type provides a standard way of representing data as a byte. Benefits of using `std::byte` over `char` or `unsigned char` is that it is not a character type, and is also not an arithmetic type; while the only operator overloads available are bitwise operations.\n```c++\nstd::byte a {0};\nstd::byte b {0xFF};\nint i = std::to_integer\u003Cint>(b); \u002F\u002F 0xFF\nstd::byte c = a & b;\nint j = std::to_integer\u003Cint>(c); \u002F\u002F 0\n```\nNote that `std::byte` is simply an enum, and braced initialization of enums become possible thanks to [direct-list-initialization of enums](#direct-list-initialization-of-enums).\n\n### Splicing for maps and sets\nMoving nodes and merging containers without the overhead of expensive copies, moves, or heap allocations\u002Fdeallocations.\n\nMoving elements from one map to another:\n```c++\nstd::map\u003Cint, string> src {{1, \"one\"}, {2, \"two\"}, {3, \"buckle my shoe\"}};\nstd::map\u003Cint, string> dst {{3, \"three\"}};\ndst.insert(src.extract(src.find(1))); \u002F\u002F Cheap remove and insert of { 1, \"one\" } from `src` to `dst`.\ndst.insert(src.extract(2)); \u002F\u002F Cheap remove and insert of { 2, \"two\" } from `src` to `dst`.\n\u002F\u002F dst == { { 1, \"one\" }, { 2, \"two\" }, { 3, \"three\" } };\n```\n\nInserting an entire set:\n```c++\nstd::set\u003Cint> src {1, 3, 5};\nstd::set\u003Cint> dst {2, 4, 5};\ndst.merge(src);\n\u002F\u002F src == { 5 }\n\u002F\u002F dst == { 1, 2, 3, 4, 5 }\n```\n\nInserting elements which outlive the container:\n```c++\nauto elementFactory() {\n  std::set\u003C...> s;\n  s.emplace(...);\n  return s.extract(s.begin());\n}\ns2.insert(elementFactory());\n```\n\nChanging the key of a map element:\n```c++\nstd::map\u003Cint, string> m {{1, \"one\"}, {2, \"two\"}, {3, \"three\"}};\nauto e = m.extract(2);\ne.key() = 4;\nm.insert(std::move(e));\n\u002F\u002F m == { { 1, \"one\" }, { 3, \"three\" }, { 4, \"two\" } }\n```\n\n### Parallel algorithms\nMany of the STL algorithms, such as the `copy`, `find` and `sort` methods, started to support the *parallel execution policies*: `seq`, `par` and `par_unseq` which translate to \"sequentially\", \"parallel\" and \"parallel unsequenced\".\n\n```c++\nstd::vector\u003Cint> longVector;\n\u002F\u002F Find element using parallel execution policy\nauto result1 = std::find(std::execution::par, std::begin(longVector), std::end(longVector), 2);\n\u002F\u002F Sort elements using sequential execution policy\nauto result2 = std::sort(std::execution::seq, std::begin(longVector), std::end(longVector));\n```\n\n### std::sample\nSamples n elements in the given sequence (without replacement) where every element has an equal chance of being selected.\n```c++\nconst std::string ALLOWED_CHARS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\nstd::string guid;\n\u002F\u002F Sample 5 characters from ALLOWED_CHARS.\nstd::sample(ALLOWED_CHARS.begin(), ALLOWED_CHARS.end(), std::back_inserter(guid),\n  5, std::mt19937{ std::random_device{}() });\n\nstd::cout \u003C\u003C guid; \u002F\u002F e.g. G1fW2\n```\n\n### std::clamp\nClamp given value between a lower and upper bound.\n```c++\nstd::clamp(42, -1, 1); \u002F\u002F == 1\nstd::clamp(-42, -1, 1); \u002F\u002F == -1\nstd::clamp(0, -1, 1); \u002F\u002F == 0\n\n\u002F\u002F `std::clamp` also accepts a custom comparator:\nstd::clamp(0, -1, 1, std::less\u003C>{}); \u002F\u002F == 0\n```\n\n### std::reduce\nFold over a given range of elements. Conceptually similar to `std::accumulate`, but `std::reduce` will perform the fold in parallel. Due to the fold being done in parallel, if you specify a binary operation, it is required to be associative and commutative. A given binary operation also should not change any element or invalidate any iterators within the given range.\n\nThe default binary operation is std::plus with an initial value of 0.\n```c++\nconst std::array\u003Cint, 3> a{ 1, 2, 3 };\nstd::reduce(std::cbegin(a), std::cend(a)); \u002F\u002F == 6\n\u002F\u002F Using a custom binary op:\nstd::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies\u003C>{}); \u002F\u002F == 6\n```\nAdditionally you can specify transformations for reducers:\n```c++\nstd::transform_reduce(std::cbegin(a), std::cend(a), 0, std::plus\u003C>{}, times_ten); \u002F\u002F == 60\n\nconst std::array\u003Cint, 3> b{ 1, 2, 3 };\nconst auto product_times_ten = [](const auto a, const auto b) { return a * b * 10; };\n\nstd::transform_reduce(std::cbegin(a), std::cend(a), std::cbegin(b), 0, std::plus\u003C>{}, product_times_ten); \u002F\u002F == 140\n```\n\n### Prefix sum algorithms\nSupport for prefix sums (both inclusive and exclusive scans) along with transformations.\n```c++\nconst std::array\u003Cint, 3> a{ 1, 2, 3 };\n\nstd::inclusive_scan(std::cbegin(a), std::cend(a),\n    std::ostream_iterator\u003Cint>{ std::cout, \" \" }, std::plus\u003C>{}); \u002F\u002F 1 3 6\n\nstd::exclusive_scan(std::cbegin(a), std::cend(a),\n    std::ostream_iterator\u003Cint>{ std::cout, \" \" }, 0, std::plus\u003C>{}); \u002F\u002F 0 1 3\n\nconst auto times_ten = [](const auto n) { return n * 10; };\n\nstd::transform_inclusive_scan(std::cbegin(a), std::cend(a),\n    std::ostream_iterator\u003Cint>{ std::cout, \" \" }, std::plus\u003C>{}, times_ten); \u002F\u002F 10 30 60\n\nstd::transform_exclusive_scan(std::cbegin(a), std::cend(a),\n    std::ostream_iterator\u003Cint>{ std::cout, \" \" }, 0, std::plus\u003C>{}, times_ten); \u002F\u002F 0 10 30\n```\n\n### GCD and LCM\nGreatest common divisor (GCD) and least common multiple (LCM).\n```c++\nconst int p = 9;\nconst int q = 3;\nstd::gcd(p, q); \u002F\u002F == 3\nstd::lcm(p, q); \u002F\u002F == 9\n```\n\n### std::not_fn\nUtility function that returns the negation of the result of the given function.\n```c++\nconst std::ostream_iterator\u003Cint> ostream_it{ std::cout, \" \" };\nconst auto is_even = [](const auto n) { return n % 2 == 0; };\nstd::vector\u003Cint> v{ 0, 1, 2, 3, 4 };\n\n\u002F\u002F Print all even numbers.\nstd::copy_if(std::cbegin(v), std::cend(v), ostream_it, is_even); \u002F\u002F 0 2 4\n\u002F\u002F Print all odd (not even) numbers.\nstd::copy_if(std::cbegin(v), std::cend(v), ostream_it, std::not_fn(is_even)); \u002F\u002F 1 3\n```\n\n### String conversion to\u002Ffrom numbers\nConvert integrals and floats to a string or vice-versa. Conversions are non-throwing, do not allocate, and are more secure than the equivalents from the C standard library.\n\nUsers are responsible for allocating enough storage required for `std::to_chars`, or the function will fail by setting the error code object in its return value.\n\nThese functions allow you to optionally pass a base (defaults to base-10) or a format specifier for floating type input.\n\n* `std::to_chars` returns a (non-const) char pointer which is one-past-the-end of the string that the function wrote to inside the given buffer, and an error code object.\n* `std::from_chars` returns a const char pointer which on success is equal to the end pointer passed to the function, and an error code object.\n\nBoth error code objects returned from these functions are equal to the default-initialized error code object on success.\n\nConvert the number `123` to a `std::string`:\n```c++\nconst int n = 123;\n\n\u002F\u002F Can use any container, string, array, etc.\nstd::string str;\nstr.resize(3); \u002F\u002F hold enough storage for each digit of `n`\n\nconst auto [ ptr, ec ] = std::to_chars(str.data(), str.data() + str.size(), n);\n\nif (ec == std::errc{}) { std::cout \u003C\u003C str \u003C\u003C std::endl; } \u002F\u002F 123\nelse { \u002F* handle failure *\u002F }\n```\n\nConvert from a `std::string` with value `\"123\"` to an integer:\n```c++\nconst std::string str{ \"123\" };\nint n;\n\nconst auto [ ptr, ec ] = std::from_chars(str.data(), str.data() + str.size(), n);\n\nif (ec == std::errc{}) { std::cout \u003C\u003C n \u003C\u003C std::endl; } \u002F\u002F 123\nelse { \u002F* handle failure *\u002F }\n```\n\n### Rounding functions for chrono durations and timepoints\nProvides abs, round, ceil, and floor helper functions for `std::chrono::duration` and `std::chrono::time_point`.\n```c++\nstd::chrono::milliseconds a{ -5500 };\nstd::chrono::milliseconds d = std::chrono::abs(a); \u002F\u002F == 5500ms\nstd::chrono::round\u003Cseconds>(d); \u002F\u002F == 6s\nstd::chrono::ceil\u003Cseconds>(d); \u002F\u002F == 6s\nstd::chrono::floor\u003Cseconds>(d); \u002F\u002F == 5s\n```\n\n## C++14 Language Features\n\n### Binary literals\nBinary literals provide a convenient way to represent a base-2 number.\nIt is possible to separate digits with `'`.\n```c++\n0b110 \u002F\u002F == 6\n0b1111'1111 \u002F\u002F == 255\n```\n\n### Generic lambda expressions\nC++14 now allows the `auto` type-specifier in the parameter list, enabling polymorphic lambdas.\n```c++\nauto identity = [](auto x) { return x; };\nint three = identity(3); \u002F\u002F == 3\nstd::string foo = identity(\"foo\"); \u002F\u002F == \"foo\"\n```\n\n### Lambda capture initializers\nThis allows creating lambda captures initialized with arbitrary expressions. The name given to the captured value does not need to be related to any variables in the enclosing scopes and introduces a new name inside the lambda body. The initializing expression is evaluated when the lambda is _created_ (not when it is _invoked_).\n```c++\nint factory(int i) { return i * 10; }\nauto f = [x = factory(2)] { return x; }; \u002F\u002F returns 20\n\nauto generator = [x = 0] () mutable {\n  \u002F\u002F this would not compile without 'mutable' as we are modifying x on each call\n  return x++;\n};\nauto a = generator(); \u002F\u002F == 0\nauto b = generator(); \u002F\u002F == 1\nauto c = generator(); \u002F\u002F == 2\n```\nBecause it is now possible to _move_ (or _forward_) values into a lambda that could previously be only captured by copy or reference we can now capture move-only types in a lambda by value. Note that in the below example the `p` in the capture-list of `task2` on the left-hand-side of `=` is a new variable private to the lambda body and does not refer to the original `p`.\n```c++\nauto p = std::make_unique\u003Cint>(1);\n\nauto task1 = [=] { *p = 5; }; \u002F\u002F ERROR: std::unique_ptr cannot be copied\n\u002F\u002F vs.\nauto task2 = [p = std::move(p)] { *p = 5; }; \u002F\u002F OK: p is move-constructed into the closure object\n\u002F\u002F the original p is empty after task2 is created\n```\nUsing this reference-captures can have different names than the referenced variable.\n```c++\nauto x = 1;\nauto f = [&r = x, x = x * 10] {\n  ++r;\n  return r + x;\n};\nf(); \u002F\u002F sets x to 2 and returns 12\n```\n\n### Return type deduction\nUsing an `auto` return type in C++14, the compiler will attempt to deduce the type for you. With lambdas, you can now deduce its return type using `auto`, which makes returning a deduced reference or rvalue reference possible.\n```c++\n\u002F\u002F Deduce return type as `int`.\nauto f(int i) {\n return i;\n}\n```\n```c++\ntemplate \u003Ctypename T>\nauto& f(T& t) {\n  return t;\n}\n\n\u002F\u002F Returns a reference to a deduced type.\nauto g = [](auto& x) -> auto& { return f(x); };\nint y = 123;\nint& z = g(y); \u002F\u002F reference to `y`\n```\n\n### decltype(auto)\nThe `decltype(auto)` type-specifier also deduces a type like `auto` does. However, it deduces return types while keeping their references and cv-qualifiers, while `auto` will not.\n```c++\nconst int x = 0;\nauto x1 = x; \u002F\u002F int\ndecltype(auto) x2 = x; \u002F\u002F const int\nint y = 0;\nint& y1 = y;\nauto y2 = y1; \u002F\u002F int\ndecltype(auto) y3 = y1; \u002F\u002F int&\nint&& z = 0;\nauto z1 = std::move(z); \u002F\u002F int\ndecltype(auto) z2 = std::move(z); \u002F\u002F int&&\n```\n```c++\n\u002F\u002F Note: Especially useful for generic code!\n\n\u002F\u002F Return type is `int`.\nauto f(const int& i) {\n return i;\n}\n\n\u002F\u002F Return type is `const int&`.\ndecltype(auto) g(const int& i) {\n return i;\n}\n\nint x = 123;\nstatic_assert(std::is_same\u003Cconst int&, decltype(f(x))>::value == 0);\nstatic_assert(std::is_same\u003Cint, decltype(f(x))>::value == 1);\nstatic_assert(std::is_same\u003Cconst int&, decltype(g(x))>::value == 1);\n```\n\nSee also: [`decltype (C++11)`](#decltype).\n\n### Relaxing constraints on constexpr functions\nIn C++11, `constexpr` function bodies could only contain a very limited set of syntaxes, including (but not limited to): `typedef`s, `using`s, and a single `return` statement. In C++14, the set of allowable syntaxes expands greatly to include the most common syntax such as `if` statements, multiple `return`s, loops, etc.\n```c++\nconstexpr int factorial(int n) {\n  if (n \u003C= 1) {\n    return 1;\n  } else {\n    return n * factorial(n - 1);\n  }\n}\nfactorial(5); \u002F\u002F == 120\n```\n\n### Variable templates\nC++14 allows variables to be templated:\n\n```c++\ntemplate\u003Cclass T>\nconstexpr T pi = T(3.1415926535897932385);\ntemplate\u003Cclass T>\nconstexpr T e  = T(2.7182818284590452353);\n```\n\n### [[deprecated]] attribute\nC++14 introduces the `[[deprecated]]` attribute to indicate that a unit (function, class, etc.) is discouraged and likely yield compilation warnings. If a reason is provided, it will be included in the warnings.\n```c++\n[[deprecated]]\nvoid old_method();\n[[deprecated(\"Use new_method instead\")]]\nvoid legacy_method();\n```\n\n## C++14 Library Features\n\n### User-defined literals for standard library types\nNew user-defined literals for standard library types, including new built-in literals for `chrono` and `basic_string`. These can be `constexpr` meaning they can be used at compile-time. Some uses for these literals include compile-time integer parsing, binary literals, and imaginary number literals.\n```c++\nusing namespace std::chrono_literals;\nauto day = 24h;\nday.count(); \u002F\u002F == 24\nstd::chrono::duration_cast\u003Cstd::chrono::minutes>(day).count(); \u002F\u002F == 1440\n```\n\n### Compile-time integer sequences\nThe class template `std::integer_sequence` represents a compile-time sequence of integers. There are a few helpers built on top:\n* `std::make_integer_sequence\u003CT, N>` - creates a sequence of `0, ..., N - 1` with type `T`.\n* `std::index_sequence_for\u003CT...>` - converts a template parameter pack into an integer sequence.\n\nConvert an array into a tuple:\n```c++\ntemplate\u003Ctypename Array, std::size_t... I>\ndecltype(auto) a2t_impl(const Array& a, std::integer_sequence\u003Cstd::size_t, I...>) {\n  return std::make_tuple(a[I]...);\n}\n\ntemplate\u003Ctypename T, std::size_t N, typename Indices = std::make_index_sequence\u003CN>>\ndecltype(auto) a2t(const std::array\u003CT, N>& a) {\n  return a2t_impl(a, Indices());\n}\n```\n\n### std::make_unique\n`std::make_unique` is the recommended way to create instances of `std::unique_ptr`s due to the following reasons:\n* Avoid having to use the `new` operator.\n* Prevents code repetition when specifying the underlying type the pointer shall hold.\n* Most importantly, it provides exception-safety. Suppose we were calling a function `foo` like so:\n```c++\nfoo(std::unique_ptr\u003CT>{new T{}}, function_that_throws(), std::unique_ptr\u003CT","该项目是一个现代C++语言和库特性的速查表。它详细介绍了从C++11到C++23版本中引入的新语言特性与库功能，包括但不限于概念（concepts）、协程（coroutines）、范围（ranges）等核心功能。通过提供具体的代码示例和技术说明，帮助开发者快速掌握并应用这些新特性于实际编程中。适合正在学习或使用C++进行开发的程序员参考，尤其对于那些希望利用最新标准来提升代码质量、性能及可维护性的开发者来说非常有用。",2,"2026-06-11 03:38:18","high_star"]