From c72f2796c0bf446782cda11648e096b761775cc3 Mon Sep 17 00:00:00 2001 From: Dmitry Tsarevich Date: Thu, 30 Sep 2021 01:51:54 +0300 Subject: [PATCH 01/39] Proofreading and fix of the link (#103) --- CONTRIBUTING.md | 2 +- CPP11.md | 4 ++-- CPP14.md | 2 +- CPP20.md | 6 +++--- README.md | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87dd3ed..bc7cf73 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ I'm not very picky about how you should contribute, but I ask that the following example of its usage. An optimal submission would also include a short real-world use case for the feature. * Make sure the feature is in the correct C++ version. * Make sure you've added the feature to the table of contents. -* Make sure you have also added the feature to the separate major C++ readme files (ie. CPP11.md, CPP14.md, etc.). +* Make sure you have also added the feature to the separate major C++ readme files (i.e. CPP11.md, CPP14.md, etc.). * Keep additions/deletions of content consistent with the cheatsheet's goals. ## Goals diff --git a/CPP11.md b/CPP11.md index c14f883..902e63a 100644 --- a/CPP11.md +++ b/CPP11.md @@ -805,7 +805,7 @@ static_assert(std::is_same::type, int>::valu ### Smart pointers C++11 introduces new smart pointers: `std::unique_ptr`, `std::shared_ptr`, `std::weak_ptr`. `std::auto_ptr` now becomes deprecated and then eventually removed in C++17. -`std::unique_ptr` is a non-copyable, movable pointer that manages its own heap-allocated memory. **Note: Prefer using the `std::make_X` helper functions as opposed to using constructors. See the sections for [std::make_unique](#stdmake_unique) and [std::make_shared](#stdmake_shared).** +`std::unique_ptr` is a non-copyable, movable pointer that manages its own heap-allocated memory. **Note: Prefer using the `std::make_X` helper functions as opposed to using constructors. See the sections for [std::make_unique](https://github.com/AnthonyCalandra/modern-cpp-features/blob/master/CPP14.md#stdmake_unique) and [std::make_shared](#stdmake_shared).** ```c++ std::unique_ptr p1 { new Foo{} }; // `p1` owns `Foo` if (p1) { @@ -952,7 +952,7 @@ auto result = handle.get(); // wait for the result ``` ### std::begin/end -`std::begin` and `std::end` free functions were added to return begin and end iterators of a container generically. These functions also work with raw arrays which do not have begin and end member functions. +`std::begin` and `std::end` free functions were added to return begin and end iterators of a container generically. These functions also work with raw arrays which do not have `begin` and `end` member functions. ```c++ template diff --git a/CPP14.md b/CPP14.md index 2a594a5..f95f028 100644 --- a/CPP14.md +++ b/CPP14.md @@ -148,7 +148,7 @@ constexpr T e = T(2.7182818284590452353); ``` ### [[deprecated]] attribute -C++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. +C++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. ```c++ [[deprecated]] void old_method(); diff --git a/CPP20.md b/CPP20.md index d8e964f..22ddecf 100644 --- a/CPP20.md +++ b/CPP20.md @@ -153,7 +153,7 @@ auto g = [] () { // ... }; ``` -The `requires` keyword is used either to start a requires clause or a requires expression: +The `requires` keyword is used either to start a `requires` clause or a `requires` expression: ```c++ template requires my_concept // `requires` clause. @@ -168,7 +168,7 @@ T add(T a, T b) { return a + b; } ``` -Note that the parameter list in a requires expression is optional. Each requirement in a requires expression are one of the following: +Note that the parameter list in a `requires` expression is optional. Each requirement in a `requires` expression are one of the following: * **Simple requirements** - asserts that the given expression is valid. @@ -297,7 +297,7 @@ while (unlikely_truthy_condition) [[unlikely]] { ``` ### Deprecate implicit capture of this -Implicitly capturing `this` in a lamdba capture using `[=]` is now deprecated; prefer capturing explicitly using `[=, this]` or `[=, *this]`. +Implicitly capturing `this` in a lambda capture using `[=]` is now deprecated; prefer capturing explicitly using `[=, this]` or `[=, *this]`. ```c++ struct int_value { int n = 0; diff --git a/README.md b/README.md index b7abe0d..21d7cb1 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ auto g = [] () { // ... }; ``` -The `requires` keyword is used either to start a requires clause or a requires expression: +The `requires` keyword is used either to start a `requires` clause or a `requires` expression: ```c++ template requires my_concept // `requires` clause. @@ -263,7 +263,7 @@ T add(T a, T b) { return a + b; } ``` -Note that the parameter list in a requires expression is optional. Each requirement in a requires expression are one of the following: +Note that the parameter list in a `requires` expression is optional. Each requirement in a `requires` expression are one of the following: * **Simple requirements** - asserts that the given expression is valid. @@ -392,7 +392,7 @@ while (unlikely_truthy_condition) [[unlikely]] { ``` ### Deprecate implicit capture of this -Implicitly capturing `this` in a lamdba capture using `[=]` is now deprecated; prefer capturing explicitly using `[=, this]` or `[=, *this]`. +Implicitly capturing `this` in a lambda capture using `[=]` is now deprecated; prefer capturing explicitly using `[=, this]` or `[=, *this]`. ```c++ struct int_value { int n = 0; @@ -1254,7 +1254,7 @@ constexpr T e = T(2.7182818284590452353); ``` ### [[deprecated]] attribute -C++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. +C++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. ```c++ [[deprecated]] void old_method(); @@ -2205,7 +2205,7 @@ auto result = handle.get(); // wait for the result ``` ### std::begin/end -`std::begin` and `std::end` free functions were added to return begin and end iterators of a container generically. These functions also work with raw arrays which do not have begin and end member functions. +`std::begin` and `std::end` free functions were added to return begin and end iterators of a container generically. These functions also work with raw arrays which do not have `begin` and `end` member functions. ```c++ template From 1343f5eeef4c41b19b6f7e68d75000758ed1f476 Mon Sep 17 00:00:00 2001 From: Chengqi Deng Date: Sat, 4 Dec 2021 07:48:04 +0800 Subject: [PATCH 02/39] Auto generate readme (#100) * Auto generate readme provided by @KinglittleQ --- .github/workflows/main.yml | 23 ++++++++++ CONTRIBUTING.md | 8 ++-- CPP11.md | 8 ++-- CPP14.md | 4 +- CPP17.md | 2 +- README.md | 32 ++++++++------ auto-generate-readme.py | 89 ++++++++++++++++++++++++++++++++++++++ readme-template.md | 26 +++++++++++ 8 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 auto-generate-readme.py create mode 100644 readme-template.md diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..9c8a3e1 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,23 @@ +name: auto-generate-readme +on: + push: + +jobs: + auto-generate-readme: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v2 + - name: Install Python3 + uses: actions/setup-python@v2 + with: + python-version: '3.7' + - name: Update README + run: python auto-generate-readme.py + - name: Commit + run: | + git config --global user.name 'Github Action Bot' + git config --global user.email 'bot@example.com' + git add -u . + git commit -m 'Update README' || echo "No changes to commit" + git push origin || echo "No changes to push" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bc7cf73..fd555a7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,10 +9,12 @@ I'm not very picky about how you should contribute, but I ask that the following * Proper spelling and grammar. * If it's a language or library feature that you can write code with, please provide an example of its usage. An optimal submission would also include a short real-world use case for the feature. -* Make sure the feature is in the correct C++ version. +* Keep additions/deletions of content consistent with the cheatsheet's goals (see below). + +#### Instructions +* Make sure the feature is in the correct C++ version file (i.e. CPP11.md, etc.). * Make sure you've added the feature to the table of contents. -* Make sure you have also added the feature to the separate major C++ readme files (i.e. CPP11.md, CPP14.md, etc.). -* Keep additions/deletions of content consistent with the cheatsheet's goals. +* Note: Please don't make changes to README.md itself -- the changes in the individual markdown files are all added to the README automatically. ## Goals My goal for this cheatsheet is to prefer conciseness over absolute completeness. Examples of features should be minimal: if an example is overly complicated, large, or is more of an obscure usage of the feature then it will most likely be rejected in review. The reason for this goal is to teach users what the most popular uses of these features will be, and for a more thorough investigation, to learn about those from external C++ resources. diff --git a/CPP11.md b/CPP11.md index 902e63a..3e996f6 100644 --- a/CPP11.md +++ b/CPP11.md @@ -153,7 +153,7 @@ auto sum(const First first, const Args... args) -> decltype(first) { } sum(1, 2, 3, 4, 5); // 15 -sum(1, 2, 3); // 6 +sum(1, 2, 3); // 6 sum(1.5, 2.0, 3.7); // 7.2 ``` @@ -270,7 +270,7 @@ auto add(X x, Y y) -> decltype(x + y) { add(1, 2.0); // `decltype(x + y)` => `decltype(3.0)` => `double` ``` -See also: `decltype(auto)` (C++14). +See also: [`decltype(auto) (C++14)`](README.md#decltypeauto). ### Type aliases Semantically similar to using a `typedef` however, type aliases with `using` are easier to read and are compatible with templates. @@ -667,7 +667,7 @@ auto add(T a, U b) -> decltype(a + b) { return a + b; } ``` -In C++14, `decltype(auto)` can be used instead. +In C++14, [`decltype(auto) (C++14)`](README.md#decltypeauto) can be used instead. ### Noexcept specifier The `noexcept` specifier specifies whether a function could throw exceptions. It is an improved version of `throw()`. @@ -779,7 +779,7 @@ void foo(bool clause) { /* do something... */ } std::vector threadsVector; threadsVector.emplace_back([]() { - // Lambda function that will be invoked + // Lambda function that will be invoked }); threadsVector.emplace_back(foo, true); // thread will run foo(true) for (auto& thread : threadsVector) { diff --git a/CPP14.md b/CPP14.md index f95f028..a95ede3 100644 --- a/CPP14.md +++ b/CPP14.md @@ -122,7 +122,7 @@ static_assert(std::is_same::value == 1); static_assert(std::is_same::value == 1); ``` -See also: `decltype` (C++11). +See also: [`decltype (C++11)`](README.md#decltype). ### Relaxing constraints on constexpr functions In 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. @@ -198,7 +198,7 @@ The compiler is free to call `new T{}`, then `function_that_throws()`, and so on foo(std::make_unique(), function_that_throws(), std::make_unique()); ``` -See the C++11 section on smart pointers for more information on `std::unique_ptr` and `std::shared_ptr`. +See the section on [smart pointers (C++11)](README.md#smart-pointers) for more information on `std::unique_ptr` and `std::shared_ptr`. ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. diff --git a/CPP17.md b/CPP17.md index 8e21dd2..3d42d6a 100644 --- a/CPP17.md +++ b/CPP17.md @@ -180,7 +180,7 @@ namespace A::B::C { ``` ### Structured bindings -A 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`, `std::pair`, `std::array`, and aggregate structures. +A 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`](README.md#tuples), `std::pair`, [`std::array`](README.md#stdarray), and aggregate structures. ```c++ using Coordinate = std::pair; Coordinate origin() { diff --git a/README.md b/README.md index 21d7cb1..a23e508 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # C++20/17/14/11 ## Overview -Many of these descriptions and examples are taken from various resources (see [Acknowledgements](#acknowledgements) section) and summarized in my own words. + C++20 includes the following new language features: - [coroutines](#coroutines) @@ -33,6 +33,7 @@ C++20 includes the following new library features: - [std::midpoint](#stdmidpoint) - [std::to_array](#stdto_array) + C++17 includes the following new language features: - [template argument deduction for class templates](#template-argument-deduction-for-class-templates) - [declaring non-type template parameters with auto](#declaring-non-type-template-parameters-with-auto) @@ -61,6 +62,7 @@ C++17 includes the following new library features: - [splicing for maps and sets](#splicing-for-maps-and-sets) - [parallel algorithms](#parallel-algorithms) + C++14 includes the following new language features: - [binary literals](#binary-literals) - [generic lambda expressions](#generic-lambda-expressions) @@ -76,6 +78,7 @@ C++14 includes the following new library features: - [compile-time integer sequences](#compile-time-integer-sequences) - [std::make_unique](#stdmake_unique) + C++11 includes the following new language features: - [move semantics](#move-semantics) - [variadic templates](#variadic-templates) @@ -128,6 +131,8 @@ C++11 includes the following new library features: - [std::async](#stdasync) - [std::begin/end](#stdbeginend) + + ## C++20 Language Features ### Coroutines @@ -353,7 +358,7 @@ auto f = [](std::vector v) { ### Range-based for loop with initializer This feature simplifies common code patterns, helps keep scopes tight, and offers an elegant solution to a common lifetime problem. ```c++ -for (std::vector v{1, 2, 3}; auto& e : v) { +for (auto v = std::vector{1, 2, 3}; auto& e : v) { std::cout << e; } // prints "123" @@ -960,7 +965,7 @@ void my_callback(std::string msg, [[maybe_unused]] bool error) { ### std::variant The 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). ```c++ -std::variant v {12}; +std::variant v{ 12 }; std::get(v); // == 12 std::get<0>(v); // == 12 v = 12.0; @@ -1228,7 +1233,7 @@ static_assert(std::is_same::value == 1); static_assert(std::is_same::value == 1); ``` -See also: [`decltype`](#decltype). +See also: [`decltype (C++11)`](#decltype). ### Relaxing constraints on constexpr functions In 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. @@ -1258,7 +1263,6 @@ C++14 introduces the `[[deprecated]]` attribute to indicate that a unit (functio ```c++ [[deprecated]] void old_method(); - [[deprecated("Use new_method instead")]] void legacy_method(); ``` @@ -1305,7 +1309,7 @@ The compiler is free to call `new T{}`, then `function_that_throws()`, and so on foo(std::make_unique(), function_that_throws(), std::make_unique()); ``` -See the section on [smart pointers](#smart-pointers) for more information on `std::unique_ptr` and `std::shared_ptr`. +See the section on [smart pointers (C++11)](#smart-pointers) for more information on `std::unique_ptr` and `std::shared_ptr`. ## C++11 Language Features @@ -1522,7 +1526,7 @@ auto add(X x, Y y) -> decltype(x + y) { add(1, 2.0); // `decltype(x + y)` => `decltype(3.0)` => `double` ``` -See also: [`decltype(auto)`](#decltypeauto). +See also: [`decltype(auto) (C++14)`](#decltypeauto). ### Type aliases Semantically similar to using a `typedef` however, type aliases with `using` are easier to read and are compatible with templates. @@ -1873,7 +1877,6 @@ struct Foo { Bar getBar() & { return bar; } Bar getBar() const& { return bar; } Bar getBar() && { return std::move(bar); } - Bar getBar() const&& { return std::move(bar); } private: Bar bar; }; @@ -1920,7 +1923,7 @@ auto add(T a, U b) -> decltype(a + b) { return a + b; } ``` -In C++14, [decltype(auto)](#decltypeauto) can be used instead. +In C++14, [`decltype(auto) (C++14)`](#decltypeauto) can be used instead. ### Noexcept specifier The `noexcept` specifier specifies whether a function could throw exceptions. It is an improved version of `throw()`. @@ -1986,7 +1989,7 @@ typename remove_reference::type&& move(T&& arg) { Transferring `std::unique_ptr`s: ```c++ -std::unique_ptr p1 {new int{0}}; // in practice, use std::make_unique +std::unique_ptr p1 {new int{0}}; // in practice, use std::make_unique std::unique_ptr p2 = p1; // error -- cannot copy unique pointers std::unique_ptr p3 = std::move(p1); // move `p1` into `p3` // now unsafe to dereference object held by `p1` @@ -2058,9 +2061,9 @@ static_assert(std::is_same::type, int>::valu ### Smart pointers C++11 introduces new smart pointers: `std::unique_ptr`, `std::shared_ptr`, `std::weak_ptr`. `std::auto_ptr` now becomes deprecated and then eventually removed in C++17. -`std::unique_ptr` is a non-copyable, movable pointer that manages its own heap-allocated memory. **Note: Prefer using the `std::make_X` helper functions as opposed to using constructors. See the sections for [std::make_unique](#stdmake_unique) and [std::make_shared](#stdmake_shared).** +`std::unique_ptr` is a non-copyable, movable pointer that manages its own heap-allocated memory. **Note: Prefer using the `std::make_X` helper functions as opposed to using constructors. See the sections for [std::make_unique](https://github.com/AnthonyCalandra/modern-cpp-features/blob/master/CPP14.md#stdmake_unique) and [std::make_shared](#stdmake_shared).** ```c++ -std::unique_ptr p1 {new Foo{}}; // `p1` owns `Foo` +std::unique_ptr p1 { new Foo{} }; // `p1` owns `Foo` if (p1) { p1->bar(); } @@ -2221,16 +2224,17 @@ auto a = CountTwos(vec); // 2 auto b = CountTwos(arr); // 1 ``` + + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. * [clang](http://clang.llvm.org/cxx_status.html) and [gcc](https://gcc.gnu.org/projects/cxx-status.html)'s standards support pages. Also included here are the proposals for language/library features that I used to help find a description of, what it's meant to fix, and some examples. * [Compiler explorer](https://godbolt.org/) -* [Scott Meyers' Effective Modern C++](https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996) - highly recommended book! +* [Scott Meyers' Effective Modern C++](https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996) - highly recommended series of books! * [Jason Turner's C++ Weekly](https://www.youtube.com/channel/UCxHAlbZQNFU2LgEtiqd2Maw) - nice collection of C++-related videos. * [What can I do with a moved-from object?](http://stackoverflow.com/questions/7027523/what-can-i-do-with-a-moved-from-object) * [What are some uses of decltype(auto)?](http://stackoverflow.com/questions/24109737/what-are-some-uses-of-decltypeauto) -* And many more SO posts I'm forgetting... ## Author Anthony Calandra diff --git a/auto-generate-readme.py b/auto-generate-readme.py new file mode 100644 index 0000000..0bb683e --- /dev/null +++ b/auto-generate-readme.py @@ -0,0 +1,89 @@ +from pathlib import Path + + +class MarkdownParser(): + + def __init__(self, text): + self.text = text + self.lines = text.split('\n') + + def title(self): + return self.lines[0].split(' ')[1] + + def header(self, name, level, include_header=False): + start = False + end = False + content = [] + mark = '#' * level + for line in self.lines: + if start and not end: + end |= (f'{mark} ' in line[:(level + 1)]) and (not f'{mark} {name}' in line) + if end: + start = False + else: + content.append(line) + else: + start = (f'{mark} {name}' in line) + if start: + end = False + if include_header: + content.append(line) + + content = '\n'.join(content) + return content + + def overview(self): + overview = self.header('Overview', 2) + overview = overview.split('\n') + overview = '\n'.join(overview[1:]) # remove the first line + return overview + + def features(self): + return self.header('C++', 2, True) + + +def combine(text, parsers): + overview = '' + features = '' + title = '' + for p in parsers: + title += p.title().replace('C++', '') + '/' + overview += p.overview() + '\n' + features += p.features() + '\n' + + title = title[:-1] + overview = overview.replace('README.md#', '#') + features = features.replace('README.md#', '#') + + text = text.replace('# C++\n', f'# C++{title}\n') + text = text.replace(f'', overview) + text = text.replace(f'', features) + + return text + + +def main(): + src_dir = Path(__file__).parent + parsers = [] + + srcs = list(src_dir.glob('CPP*.md')) + srcs.sort(reverse=True) + for file in srcs: + with open(file, 'r') as fp: + text = fp.read() + p = MarkdownParser(text) + parsers.append(p) + + template_file = src_dir / 'readme-template.md' + with open(template_file, 'r') as fp: + text = fp.read() + + text = combine(text, parsers) + + readme_file = src_dir / 'README.md' + with open(readme_file, 'w') as fp: + fp.write(text) + + +if __name__ == '__main__': + main() diff --git a/readme-template.md b/readme-template.md new file mode 100644 index 0000000..fc54b91 --- /dev/null +++ b/readme-template.md @@ -0,0 +1,26 @@ +# C++ + +## Overview + + + + + +## Acknowledgements +* [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. +* [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. +* [clang](http://clang.llvm.org/cxx_status.html) and [gcc](https://gcc.gnu.org/projects/cxx-status.html)'s standards support pages. Also included here are the proposals for language/library features that I used to help find a description of, what it's meant to fix, and some examples. +* [Compiler explorer](https://godbolt.org/) +* [Scott Meyers' Effective Modern C++](https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996) - highly recommended series of books! +* [Jason Turner's C++ Weekly](https://www.youtube.com/channel/UCxHAlbZQNFU2LgEtiqd2Maw) - nice collection of C++-related videos. +* [What can I do with a moved-from object?](http://stackoverflow.com/questions/7027523/what-can-i-do-with-a-moved-from-object) +* [What are some uses of decltype(auto)?](http://stackoverflow.com/questions/24109737/what-are-some-uses-of-decltypeauto) + +## Author +Anthony Calandra + +## Content Contributors +See: https://github.com/AnthonyCalandra/modern-cpp-features/graphs/contributors + +## License +MIT From a39f7b8ddee59170e6600f438ad036e1fd8ec0ab Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 3 Dec 2021 18:50:50 -0500 Subject: [PATCH 03/39] Update license year to 2022. --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 2077539..fa7cfa2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2020 Anthony Calandra +Copyright (c) 2022 Anthony Calandra Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From 2da0071af082653388f30176de39480a779a1ef0 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 21 Feb 2022 13:48:13 -0500 Subject: [PATCH 04/39] Trigger workflows when pushing or opening PRs to the master branch. --- .github/workflows/main.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9c8a3e1..e588b01 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,9 @@ name: auto-generate-readme on: push: + branches: [master] + pull_request: + branches: [master] jobs: auto-generate-readme: @@ -8,6 +11,9 @@ jobs: steps: - name: Check out repository code uses: actions/checkout@v2 + with: + ref: ${{github.event.pull_request.head.ref}} + repository: ${{github.event.pull_request.head.repo.full_name}} - name: Install Python3 uses: actions/setup-python@v2 with: From 1f1461ecfcdd18c2f2768cfd72ba9c302183894b Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 21 Feb 2022 14:54:25 -0500 Subject: [PATCH 05/39] Update CONTRIBUTING.md Remove the note about README.md automatically changing. --- CONTRIBUTING.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd555a7..4403694 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,6 @@ example of its usage. An optimal submission would also include a short real-worl #### Instructions * Make sure the feature is in the correct C++ version file (i.e. CPP11.md, etc.). * Make sure you've added the feature to the table of contents. -* Note: Please don't make changes to README.md itself -- the changes in the individual markdown files are all added to the README automatically. ## Goals My goal for this cheatsheet is to prefer conciseness over absolute completeness. Examples of features should be minimal: if an example is overly complicated, large, or is more of an obscure usage of the feature then it will most likely be rejected in review. The reason for this goal is to teach users what the most popular uses of these features will be, and for a more thorough investigation, to learn about those from external C++ resources. From cb50e8e5a65a8fcc4b2ad2987ef712de62a4dd3f Mon Sep 17 00:00:00 2001 From: dimalosev0605 <50060117+dimalosev0605@users.noreply.github.com> Date: Wed, 23 Feb 2022 18:54:35 +0300 Subject: [PATCH 06/39] Update CPP11.md (#109) * Update CPP11.md semicolons absence * Update README.md semicolons absence --- CPP11.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CPP11.md b/CPP11.md index 3e996f6..f40e4e9 100644 --- a/CPP11.md +++ b/CPP11.md @@ -82,10 +82,10 @@ void f(int&& x) {} f(x); // calls f(int&) f(xl); // calls f(int&) f(3); // calls f(int&&) -f(std::move(x)) // calls f(int&&) +f(std::move(x)); // calls f(int&&) f(xr2); // calls f(int&) -f(std::move(xr2)) // calls f(int&& x) +f(std::move(xr2)); // calls f(int&& x) ``` See also: [`std::move`](#stdmove), [`std::forward`](#stdforward), [`forwarding references`](#forwarding-references). diff --git a/README.md b/README.md index a23e508..fa93ca6 100644 --- a/README.md +++ b/README.md @@ -1338,10 +1338,10 @@ void f(int&& x) {} f(x); // calls f(int&) f(xl); // calls f(int&) f(3); // calls f(int&&) -f(std::move(x)) // calls f(int&&) +f(std::move(x)); // calls f(int&&) f(xr2); // calls f(int&) -f(std::move(xr2)) // calls f(int&& x) +f(std::move(xr2)); // calls f(int&& x) ``` See also: [`std::move`](#stdmove), [`std::forward`](#stdforward), [`forwarding references`](#forwarding-references). From bd4cb84e80fee6c0bf428b17a92c0799e1b2d696 Mon Sep 17 00:00:00 2001 From: Arsenic <54987647+Arsenic-ATG@users.noreply.github.com> Date: Sat, 19 Mar 2022 21:40:40 +0530 Subject: [PATCH 07/39] C++17: Add __has_include operator (#112) --- CPP17.md | 38 ++++++++++++++++++++++++++++++++++++++ README.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/CPP17.md b/CPP17.md index 3d42d6a..9898ac9 100644 --- a/CPP17.md +++ b/CPP17.md @@ -18,6 +18,7 @@ C++17 includes the following new language features: - [utf-8 character literals](#utf-8-character-literals) - [direct-list-initialization of enums](#direct-list-initialization-of-enums) - [fallthrough, nodiscard, maybe_unused attributes](#fallthrough-nodiscard-maybe_unused-attributes) +- [\_\_has\_include](#\_\_has\_include) C++17 includes the following new library features: - [std::variant](#stdvariant) @@ -309,6 +310,43 @@ void my_callback(std::string msg, [[maybe_unused]] bool error) { } ``` +### \_\_has\_include + +`__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. + +One use case of this would be using two libraries that work the same way, using the backup/experimental one if the preferred one is not found on the system. + +```c++ +#ifdef __has_include +# if __has_include() +# include +# define have_optional 1 +# elif __has_include() +# include +# define have_optional 1 +# define experimental_optional +# else +# define have_optional 0 +# endif +#endif +``` + +It 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. + +```c++ +#ifdef __has_include +# if __has_include() +# include +# include +# elif __has_include() +# include +# include +# else +# error No suitable OpenGL headers found. +# endif +#endif +``` + ## C++17 Library Features ### std::variant diff --git a/README.md b/README.md index fa93ca6..047be8d 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ C++17 includes the following new language features: - [utf-8 character literals](#utf-8-character-literals) - [direct-list-initialization of enums](#direct-list-initialization-of-enums) - [fallthrough, nodiscard, maybe_unused attributes](#fallthrough-nodiscard-maybe_unused-attributes) +- [\_\_has\_include](#\_\_has\_include) C++17 includes the following new library features: - [std::variant](#stdvariant) @@ -960,6 +961,43 @@ void my_callback(std::string msg, [[maybe_unused]] bool error) { } ``` +### \_\_has\_include + +`__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. + +One use case of this would be using two libraries that work the same way, using the backup/experimental one if the preferred one is not found on the system. + +```c++ +#ifdef __has_include +# if __has_include() +# include +# define have_optional 1 +# elif __has_include() +# include +# define have_optional 1 +# define experimental_optional +# else +# define have_optional 0 +# endif +#endif +``` + +It 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. + +```c++ +#ifdef __has_include +# if __has_include() +# include +# include +# elif __has_include() +# include +# include +# else +# error No suitable OpenGL headers found. +# endif +#endif +``` + ## C++17 Library Features ### std::variant From 40b3823256e4070c10b258099424aecfc397a0c3 Mon Sep 17 00:00:00 2001 From: clepz Date: Tue, 1 Nov 2022 19:53:49 +0300 Subject: [PATCH 08/39] fallthrough explanation and example are fixed. (#115) * fallthrough explanation and example are fixed. * Sentence typo fixed and written more concisely. --- CPP17.md | 10 ++++++++-- README.md | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CPP17.md b/CPP17.md index 9898ac9..51e4683 100644 --- a/CPP17.md +++ b/CPP17.md @@ -266,14 +266,20 @@ byte e = byte{256}; // ERROR ### fallthrough, nodiscard, maybe_unused attributes C++17 introduces three new attributes: `[[fallthrough]]`, `[[nodiscard]]` and `[[maybe_unused]]`. -* `[[fallthrough]]` indicates to the compiler that falling through in a switch statement is intended behavior. +* `[[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/default label. ```c++ switch (n) { - case 1: [[fallthrough]] + case 1: // ... + [[fallthrough]]; case 2: // ... break; + case 3: + // ... + [[fallthrough]]; + default: + // ... } ``` diff --git a/README.md b/README.md index 047be8d..980446d 100644 --- a/README.md +++ b/README.md @@ -917,14 +917,20 @@ byte e = byte{256}; // ERROR ### fallthrough, nodiscard, maybe_unused attributes C++17 introduces three new attributes: `[[fallthrough]]`, `[[nodiscard]]` and `[[maybe_unused]]`. -* `[[fallthrough]]` indicates to the compiler that falling through in a switch statement is intended behavior. +* `[[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/default label. ```c++ switch (n) { - case 1: [[fallthrough]] + case 1: // ... + [[fallthrough]]; case 2: // ... break; + case 3: + // ... + [[fallthrough]]; + default: + // ... } ``` From 0dd38f0badfd6c18f90fade6a9da438894a28e8b Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 17 Feb 2023 17:03:16 -0500 Subject: [PATCH 09/39] Improve constexpr section by providing a small explanation of one of the snippets and that evaluations MAY happen at compile-time. --- CPP11.md | 5 +++-- README.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CPP11.md b/CPP11.md index f40e4e9..ae6e9ea 100644 --- a/CPP11.md +++ b/CPP11.md @@ -312,7 +312,7 @@ Attributes provide a universal syntax over `__attribute__(...)`, `__declspec`, e ``` ### constexpr -Constant expressions are expressions evaluated by the compiler at compile-time. Only non-complex computations can be carried out in a constant expression. Use the `constexpr` specifier to indicate the variable, function, etc. is a constant expression. +Constant expressions are expressions that are *possibly* evaluated by the compiler at compile-time. Only non-complex computations can be carried out in a constant expression (these rules are progressively relaxed in later versions). Use the `constexpr` specifier to indicate the variable, function, etc. is a constant expression. ```c++ constexpr int square(int x) { return x * x; @@ -328,8 +328,9 @@ int b = square2(2); // mov edi, 2 // call square2(int) // mov DWORD PTR [rbp-8], eax ``` +In the previous snippet, notice that the computation when calling `square` is carried out at compile-time, and then the result is embedded in the code generation, while `square2` is called at run-time. -`constexpr` values are those that the compiler can evaluate at compile-time: +`constexpr` values are those that the compiler can evaluate, but are not guaranteed to, at compile-time: ```c++ const int x = 123; constexpr const int& y = x; // error -- constexpr variable `y` must be initialized by a constant expression diff --git a/README.md b/README.md index 980446d..8f4ad46 100644 --- a/README.md +++ b/README.md @@ -1612,7 +1612,7 @@ Attributes provide a universal syntax over `__attribute__(...)`, `__declspec`, e ``` ### constexpr -Constant expressions are expressions evaluated by the compiler at compile-time. Only non-complex computations can be carried out in a constant expression. Use the `constexpr` specifier to indicate the variable, function, etc. is a constant expression. +Constant expressions are expressions that are *possibly* evaluated by the compiler at compile-time. Only non-complex computations can be carried out in a constant expression (these rules are progressively relaxed in later versions). Use the `constexpr` specifier to indicate the variable, function, etc. is a constant expression. ```c++ constexpr int square(int x) { return x * x; @@ -1628,8 +1628,9 @@ int b = square2(2); // mov edi, 2 // call square2(int) // mov DWORD PTR [rbp-8], eax ``` +In the previous snippet, notice that the computation when calling `square` is carried out at compile-time, and then the result is embedded in the code generation, while `square2` is called at run-time. -`constexpr` values are those that the compiler can evaluate at compile-time: +`constexpr` values are those that the compiler can evaluate, but are not guaranteed to, at compile-time: ```c++ const int x = 123; constexpr const int& y = x; // error -- constexpr variable `y` must be initialized by a constant expression From e2f9058ca7961fb97b1f4308256ca8d61107a9b9 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 17 Feb 2023 17:27:56 -0500 Subject: [PATCH 10/39] Add constinit specifier. --- CPP20.md | 11 +++++++++++ README.md | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/CPP20.md b/CPP20.md index 22ddecf..ae26270 100644 --- a/CPP20.md +++ b/CPP20.md @@ -18,6 +18,7 @@ C++20 includes the following new language features: - [using enum](#using-enum) - [lambda capture of parameter pack](#lambda-capture-of-parameter-pack) - [char8_t](#char8_t) +- [constinit](#constinit) C++20 includes the following new library features: - [concepts library](#concepts-library) @@ -435,6 +436,16 @@ Provides a standard type for representing UTF-8 strings. char8_t utf8_str[] = u8"\u0123"; ``` +### constinit +The `constinit` specifier requires that a variable must be initialized at compile-time. +```c++ +const char* g() { return "dynamic initialization"; } +constexpr const char* f(bool p) { return p ? "constant initializer" : g(); } + +constinit const char* c = f(true); // OK +constinit const char* d = f(false); // ERROR: `g` is not constexpr, so `d` cannot be evaluated at compile-time. +``` + ## C++20 Library Features ### Concepts library diff --git a/README.md b/README.md index 8f4ad46..82132c6 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ C++20 includes the following new language features: - [using enum](#using-enum) - [lambda capture of parameter pack](#lambda-capture-of-parameter-pack) - [char8_t](#char8_t) +- [constinit](#constinit) C++20 includes the following new library features: - [concepts library](#concepts-library) @@ -536,6 +537,16 @@ Provides a standard type for representing UTF-8 strings. char8_t utf8_str[] = u8"\u0123"; ``` +### constinit +The `constinit` specifier requires that a variable must be initialized at compile-time. +```c++ +const char* g() { return "dynamic initialization"; } +constexpr const char* f(bool p) { return p ? "constant initializer" : g(); } + +constinit const char* c = f(true); // OK +constinit const char* d = f(false); // ERROR: `g` is not constexpr, so `d` cannot be evaluated at compile-time. +``` + ## C++20 Library Features ### Concepts library From b6c45151082c98ff9d1753418ca5844318116ac7 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 17 Feb 2023 17:28:14 -0500 Subject: [PATCH 11/39] Add std::sample to C++17 section. --- CPP17.md | 13 +++++++++++++ README.md | 14 +++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CPP17.md b/CPP17.md index 51e4683..bb41ca8 100644 --- a/CPP17.md +++ b/CPP17.md @@ -31,6 +31,7 @@ C++17 includes the following new library features: - [std::byte](#stdbyte) - [splicing for maps and sets](#splicing-for-maps-and-sets) - [parallel algorithms](#parallel-algorithms) +- [std::sample](#stdsample) ## C++17 Language Features @@ -522,6 +523,18 @@ auto result1 = std::find(std::execution::par, std::begin(longVector), std::end(l auto result2 = std::sort(std::execution::seq, std::begin(longVector), std::end(longVector)); ``` +### std::sample +Samples n elements in the given sequence (without replacement) where every element has an equal chance of being selected. +```c++ +const std::string ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; +std::string guid; +// Sample 5 characters from ALLOWED_CHARS. +std::sample(ALLOWED_CHARS.begin(), ALLOWED_CHARS.end(), std::back_inserter(guid), + 5, std::mt19937{ std::random_device{}() }); + +std::cout << guid; // e.g. G1fW2 +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index 82132c6..21b2c13 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ C++17 includes the following new library features: - [std::byte](#stdbyte) - [splicing for maps and sets](#splicing-for-maps-and-sets) - [parallel algorithms](#parallel-algorithms) - +- [std::sample](#stdsample) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1184,6 +1184,18 @@ auto result1 = std::find(std::execution::par, std::begin(longVector), std::end(l auto result2 = std::sort(std::execution::seq, std::begin(longVector), std::end(longVector)); ``` +### std::sample +Samples n elements in the given sequence (without replacement) where every element has an equal chance of being selected. +```c++ +const std::string ALLOWED_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; +std::string guid; +// Sample 5 characters from ALLOWED_CHARS. +std::sample(ALLOWED_CHARS.begin(), ALLOWED_CHARS.end(), std::back_inserter(guid), + 5, std::mt19937{ std::random_device{}() }); + +std::cout << guid; // e.g. G1fW2 +``` + ## C++14 Language Features ### Binary literals From 8183b4bbdbc1fcf122aae9e06bdf0224310fb4f7 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 17 Feb 2023 19:58:05 -0500 Subject: [PATCH 12/39] Improve the std::span section. --- CPP20.md | 58 +++++++++++++++++++++++++++++++------------------------ README.md | 58 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 66 insertions(+), 50 deletions(-) diff --git a/CPP20.md b/CPP20.md index ae26270..dcca6a8 100644 --- a/CPP20.md +++ b/CPP20.md @@ -482,40 +482,48 @@ std::osyncstream{std::cout} << "The value of x is:" << x << std::endl; ``` ### std::span -A 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. Spans can be dynamically-sized or fixed-sized. +A 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/iterator and length field, a span wraps both of those up in a single object. + +Spans can be dynamically-sized or fixed-sized (known as their *extent*). Fixed-sized spans benefit from bounds-checking. + +Span doesn't propogate const so to construct a read-only span use `std::span`. + +Example: using a dynamically-sized span to print integers from various containers. ```c++ -void f(std::span ints) { - std::for_each(ints.begin(), ints.end(), [](auto i) { - // ... - }); +void print_ints(std::span ints) { + for (const auto n : ints) { + std::cout << n << std::endl; + } } -std::vector v = {1, 2, 3}; -f(v); -std::array a = {1, 2, 3}; -f(a); +print_ints(std::vector{ 1, 2, 3 }); +print_ints(std::array{ 1, 2, 3, 4, 5 }); + +int a[10] = { 0 }; +print_ints(a); // etc. ``` -Example: as opposed to maintaining a pointer and length field, a span wraps both of those up in a single container. + +Example: a statically-sized span will fail to compile for containers that don't match the extent of the span. ```c++ -constexpr size_t LENGTH_ELEMENTS = 3; -int* arr = new int[LENGTH_ELEMENTS]; // arr = {0, 0, 0} +void print_three_ints(std::span ints) { + for (const auto n : ints) { + std::cout << n << std::endl; + } +} -// Fixed-sized span which provides a view of `arr`. -std::span span = arr; -span[1] = 1; // arr = {0, 1, 0} +print_three_ints(std::vector{ 1, 2, 3 }); // ERROR +print_three_ints(std::array{ 1, 2, 3, 4, 5 }); // ERROR +int a[10] = { 0 }; +print_three_ints(a); // ERROR -// Dynamic-sized span which provides a view of `arr`. -std::span d_span = arr; -span[0] = 1; // arr = {1, 1, 0} -``` -```c++ -constexpr size_t LENGTH_ELEMENTS = 3; -int* arr = new int[LENGTH_ELEMENTS]; +std::array b = { 1, 2, 3 }; +print_three_ints(b); // OK -std::span span = arr; // OK -std::span span2 = arr; // ERROR -std::span span3 = arr; // ERROR +// You can construct a span manually if required: +std::vector c{ 1, 2, 3 }; +print_three_ints(std::span{ c.data(), 3 }); // OK: set pointer and length field. +print_three_ints(std::span{ c.cbegin(), c.cend() }); // OK: use iterator pairs. ``` ### Bit operations diff --git a/README.md b/README.md index 21b2c13..cb40c71 100644 --- a/README.md +++ b/README.md @@ -583,40 +583,48 @@ std::osyncstream{std::cout} << "The value of x is:" << x << std::endl; ``` ### std::span -A 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. Spans can be dynamically-sized or fixed-sized. +A 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/iterator and length field, a span wraps both of those up in a single object. + +Spans can be dynamically-sized or fixed-sized (known as their *extent*). Fixed-sized spans benefit from bounds-checking. + +Span doesn't propogate const so to construct a read-only span use `std::span`. + +Example: using a dynamically-sized span to print integers from various containers. ```c++ -void f(std::span ints) { - std::for_each(ints.begin(), ints.end(), [](auto i) { - // ... - }); +void print_ints(std::span ints) { + for (const auto n : ints) { + std::cout << n << std::endl; + } } -std::vector v = {1, 2, 3}; -f(v); -std::array a = {1, 2, 3}; -f(a); +print_ints(std::vector{ 1, 2, 3 }); +print_ints(std::array{ 1, 2, 3, 4, 5 }); + +int a[10] = { 0 }; +print_ints(a); // etc. ``` -Example: as opposed to maintaining a pointer and length field, a span wraps both of those up in a single container. + +Example: a statically-sized span will fail to compile for containers that don't match the extent of the span. ```c++ -constexpr size_t LENGTH_ELEMENTS = 3; -int* arr = new int[LENGTH_ELEMENTS]; // arr = {0, 0, 0} +void print_three_ints(std::span ints) { + for (const auto n : ints) { + std::cout << n << std::endl; + } +} -// Fixed-sized span which provides a view of `arr`. -std::span span = arr; -span[1] = 1; // arr = {0, 1, 0} +print_three_ints(std::vector{ 1, 2, 3 }); // ERROR +print_three_ints(std::array{ 1, 2, 3, 4, 5 }); // ERROR +int a[10] = { 0 }; +print_three_ints(a); // ERROR -// Dynamic-sized span which provides a view of `arr`. -std::span d_span = arr; -span[0] = 1; // arr = {1, 1, 0} -``` -```c++ -constexpr size_t LENGTH_ELEMENTS = 3; -int* arr = new int[LENGTH_ELEMENTS]; +std::array b = { 1, 2, 3 }; +print_three_ints(b); // OK -std::span span = arr; // OK -std::span span2 = arr; // ERROR -std::span span3 = arr; // ERROR +// You can construct a span manually if required: +std::vector c{ 1, 2, 3 }; +print_three_ints(std::span{ c.data(), 3 }); // OK: set pointer and length field. +print_three_ints(std::span{ c.cbegin(), c.cend() }); // OK: use iterator pairs. ``` ### Bit operations From 6ba2efe088b37e1a32bd575b459f941d419d64e4 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 17 Feb 2023 21:49:15 -0500 Subject: [PATCH 13/39] Simplify std::invoke example. --- CPP17.md | 19 ++++++++++--------- README.md | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/CPP17.md b/CPP17.md index bb41ca8..2764761 100644 --- a/CPP17.md +++ b/CPP17.md @@ -416,23 +416,24 @@ v; // == "trim me" ``` ### std::invoke -Invoke a `Callable` object with parameters. Examples of `Callable` objects are `std::function` or `std::bind` where an object can be called similarly to a regular function. +Invoke a `Callable` object with parameters. Examples of *callable* objects are `std::function` or lambdas; objects that can be called similarly to a regular function. ```c++ template class Proxy { - Callable c; + Callable c_; + public: - Proxy(Callable c): c(c) {} - template + Proxy(Callable c) : c_{ std::move(c) } {} + + template decltype(auto) operator()(Args&&... args) { // ... - return std::invoke(c, std::forward(args)...); + return std::invoke(c_, std::forward(args)...); } }; -auto add = [](int x, int y) { - return x + y; -}; -Proxy p {add}; + +const auto add = [](int x, int y) { return x + y; }; +Proxy p{ add }; p(1, 2); // == 3 ``` diff --git a/README.md b/README.md index cb40c71..cf6cac7 100644 --- a/README.md +++ b/README.md @@ -1085,23 +1085,24 @@ v; // == "trim me" ``` ### std::invoke -Invoke a `Callable` object with parameters. Examples of `Callable` objects are `std::function` or `std::bind` where an object can be called similarly to a regular function. +Invoke a `Callable` object with parameters. Examples of *callable* objects are `std::function` or lambdas; objects that can be called similarly to a regular function. ```c++ template class Proxy { - Callable c; + Callable c_; + public: - Proxy(Callable c): c(c) {} - template + Proxy(Callable c) : c_{ std::move(c) } {} + + template decltype(auto) operator()(Args&&... args) { // ... - return std::invoke(c, std::forward(args)...); + return std::invoke(c_, std::forward(args)...); } }; -auto add = [](int x, int y) { - return x + y; -}; -Proxy p {add}; + +const auto add = [](int x, int y) { return x + y; }; +Proxy p{ add }; p(1, 2); // == 3 ``` From 698ac6d5ff45e8f41d5ce0dca440e33f16111819 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Fri, 17 Feb 2023 23:06:23 -0500 Subject: [PATCH 14/39] Minor cosmetic changes: make attribute headers consistent; remove extra spacing in TOC. --- CPP17.md | 4 ++-- CPP20.md | 4 ++-- README.md | 13 ++++--------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/CPP17.md b/CPP17.md index 2764761..630325e 100644 --- a/CPP17.md +++ b/CPP17.md @@ -17,7 +17,7 @@ C++17 includes the following new language features: - [constexpr if](#constexpr-if) - [utf-8 character literals](#utf-8-character-literals) - [direct-list-initialization of enums](#direct-list-initialization-of-enums) -- [fallthrough, nodiscard, maybe_unused attributes](#fallthrough-nodiscard-maybe_unused-attributes) +- [\[\[fallthrough\]\], \[\[nodiscard\]\], \[\[maybe_unused\]\] attributes](#fallthrough-nodiscard-maybe_unused-attributes) - [\_\_has\_include](#\_\_has\_include) C++17 includes the following new library features: @@ -265,7 +265,7 @@ byte d = byte{1}; // OK byte e = byte{256}; // ERROR ``` -### fallthrough, nodiscard, maybe_unused attributes +### \[\[fallthrough\]\], \[\[nodiscard\]\], \[\[maybe_unused\]\] attributes C++17 introduces three new attributes: `[[fallthrough]]`, `[[nodiscard]]` and `[[maybe_unused]]`. * `[[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/default label. ```c++ diff --git a/CPP20.md b/CPP20.md index dcca6a8..61df1fe 100644 --- a/CPP20.md +++ b/CPP20.md @@ -9,7 +9,7 @@ C++20 includes the following new language features: - [designated initializers](#designated-initializers) - [template syntax for lambdas](#template-syntax-for-lambdas) - [range-based for loop with initializer](#range-based-for-loop-with-initializer) -- [likely and unlikely attributes](#likely-and-unlikely-attributes) +- [\[\[likely\]\] and \[\[unlikely\]\] attributes](#likely-and-unlikely-attributes) - [deprecate implicit capture of this](#deprecate-implicit-capture-of-this) - [class types in non-type template parameters](#class-types-in-non-type-template-parameters) - [constexpr virtual functions](#constexpr-virtual-functions) @@ -265,7 +265,7 @@ for (auto v = std::vector{1, 2, 3}; auto& e : v) { // prints "123" ``` -### likely and unlikely attributes +### \[\[likely\]\] and \[\[unlikely\]\] attributes Provides a hint to the optimizer that the labelled statement has a high probability of being executed. ```c++ switch (n) { diff --git a/README.md b/README.md index cf6cac7..8e92528 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,13 @@ ## Overview - C++20 includes the following new language features: - [coroutines](#coroutines) - [concepts](#concepts) - [designated initializers](#designated-initializers) - [template syntax for lambdas](#template-syntax-for-lambdas) - [range-based for loop with initializer](#range-based-for-loop-with-initializer) -- [likely and unlikely attributes](#likely-and-unlikely-attributes) +- [\[\[likely\]\] and \[\[unlikely\]\] attributes](#likely-and-unlikely-attributes) - [deprecate implicit capture of this](#deprecate-implicit-capture-of-this) - [class types in non-type template parameters](#class-types-in-non-type-template-parameters) - [constexpr virtual functions](#constexpr-virtual-functions) @@ -34,7 +33,6 @@ C++20 includes the following new library features: - [std::midpoint](#stdmidpoint) - [std::to_array](#stdto_array) - C++17 includes the following new language features: - [template argument deduction for class templates](#template-argument-deduction-for-class-templates) - [declaring non-type template parameters with auto](#declaring-non-type-template-parameters-with-auto) @@ -49,7 +47,7 @@ C++17 includes the following new language features: - [constexpr if](#constexpr-if) - [utf-8 character literals](#utf-8-character-literals) - [direct-list-initialization of enums](#direct-list-initialization-of-enums) -- [fallthrough, nodiscard, maybe_unused attributes](#fallthrough-nodiscard-maybe_unused-attributes) +- [\[\[fallthrough\]\], \[\[nodiscard\]\], \[\[maybe_unused\]\] attributes](#fallthrough-nodiscard-maybe_unused-attributes) - [\_\_has\_include](#\_\_has\_include) C++17 includes the following new library features: @@ -80,7 +78,6 @@ C++14 includes the following new library features: - [compile-time integer sequences](#compile-time-integer-sequences) - [std::make_unique](#stdmake_unique) - C++11 includes the following new language features: - [move semantics](#move-semantics) - [variadic templates](#variadic-templates) @@ -133,8 +130,6 @@ C++11 includes the following new library features: - [std::async](#stdasync) - [std::begin/end](#stdbeginend) - - ## C++20 Language Features ### Coroutines @@ -366,7 +361,7 @@ for (auto v = std::vector{1, 2, 3}; auto& e : v) { // prints "123" ``` -### likely and unlikely attributes +### \[\[likely\]\] and \[\[unlikely\]\] attributes Provides a hint to the optimizer that the labelled statement has a high probability of being executed. ```c++ switch (n) { @@ -934,7 +929,7 @@ byte d = byte{1}; // OK byte e = byte{256}; // ERROR ``` -### fallthrough, nodiscard, maybe_unused attributes +### \[\[fallthrough\]\], \[\[nodiscard\]\], \[\[maybe_unused\]\] attributes C++17 introduces three new attributes: `[[fallthrough]]`, `[[nodiscard]]` and `[[maybe_unused]]`. * `[[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/default label. ```c++ From 560e1b4390fd85e530e36778d50c5e1851f3849f Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Sat, 18 Feb 2023 21:37:51 -0500 Subject: [PATCH 15/39] Add std::clamp --- CPP17.md | 12 ++++++++++++ README.md | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/CPP17.md b/CPP17.md index 630325e..8d5b4b3 100644 --- a/CPP17.md +++ b/CPP17.md @@ -32,6 +32,7 @@ C++17 includes the following new library features: - [splicing for maps and sets](#splicing-for-maps-and-sets) - [parallel algorithms](#parallel-algorithms) - [std::sample](#stdsample) +- [std::clamp](#stdclamp) ## C++17 Language Features @@ -536,6 +537,17 @@ std::sample(ALLOWED_CHARS.begin(), ALLOWED_CHARS.end(), std::back_inserter(guid) std::cout << guid; // e.g. G1fW2 ``` +### std::clamp +Clamp given value between a lower and upper bound. +```c++ +std::clamp(42, -1, 1); // == 1 +std::clamp(-42, -1, 1); // == -1 +std::clamp(0, -1, 1); // == 0 + +// `std::clamp` also accepts a custom comparator: +std::clamp(0, -1, 1, std::less<>{}); // == 0 +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index 8e92528..3d59801 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ C++17 includes the following new library features: - [splicing for maps and sets](#splicing-for-maps-and-sets) - [parallel algorithms](#parallel-algorithms) - [std::sample](#stdsample) +- [std::clamp](#stdclamp) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1200,6 +1201,17 @@ std::sample(ALLOWED_CHARS.begin(), ALLOWED_CHARS.end(), std::back_inserter(guid) std::cout << guid; // e.g. G1fW2 ``` +### std::clamp +Clamp given value between a lower and upper bound. +```c++ +std::clamp(42, -1, 1); // == 1 +std::clamp(-42, -1, 1); // == -1 +std::clamp(0, -1, 1); // == 0 + +// `std::clamp` also accepts a custom comparator: +std::clamp(0, -1, 1, std::less<>{}); // == 0 +``` + ## C++14 Language Features ### Binary literals From 3ade18fb41ca5a883d8324e0d89a55daf0c53a2a Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 20 Feb 2023 18:12:16 -0500 Subject: [PATCH 16/39] Add std::reduce. --- CPP17.md | 12 ++++++++++++ README.md | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/CPP17.md b/CPP17.md index 8d5b4b3..9e47a3b 100644 --- a/CPP17.md +++ b/CPP17.md @@ -33,6 +33,7 @@ C++17 includes the following new library features: - [parallel algorithms](#parallel-algorithms) - [std::sample](#stdsample) - [std::clamp](#stdclamp) +- [std::reduce](#stdreduce) ## C++17 Language Features @@ -548,6 +549,17 @@ std::clamp(0, -1, 1); // == 0 std::clamp(0, -1, 1, std::less<>{}); // == 0 ``` +### std::reduce +Fold 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. + +The default binary operation is std::plus with an initial value of 0. +```c++ +const std::array a{ 1, 2, 3 }; +std::reduce(std::cbegin(a), std::cend(a)); // == 6 +// Using a custom binary op: +std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index 3d59801..fae127b 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ C++17 includes the following new library features: - [parallel algorithms](#parallel-algorithms) - [std::sample](#stdsample) - [std::clamp](#stdclamp) +- [std::reduce](#stdreduce) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1212,6 +1213,17 @@ std::clamp(0, -1, 1); // == 0 std::clamp(0, -1, 1, std::less<>{}); // == 0 ``` +### std::reduce +Fold 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. + +The default binary operation is std::plus with an initial value of 0. +```c++ +const std::array a{ 1, 2, 3 }; +std::reduce(std::cbegin(a), std::cend(a)); // == 6 +// Using a custom binary op: +std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 +``` + ## C++14 Language Features ### Binary literals From abab8bb1a3debca894fd44d5ce378ca88549c269 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 20 Feb 2023 19:23:51 -0500 Subject: [PATCH 17/39] Add the prefix sum algorithms. --- CPP17.md | 21 +++++++++++++++++++++ README.md | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/CPP17.md b/CPP17.md index 9e47a3b..a4b2492 100644 --- a/CPP17.md +++ b/CPP17.md @@ -34,6 +34,7 @@ C++17 includes the following new library features: - [std::sample](#stdsample) - [std::clamp](#stdclamp) - [std::reduce](#stdreduce) +- [prefix sum algorithms](#prefix-sum-algorithms) ## C++17 Language Features @@ -560,6 +561,26 @@ std::reduce(std::cbegin(a), std::cend(a)); // == 6 std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 ``` +### Prefix sum algorithms +Support for prefix sums (both inclusive and exclusive scans) along with transformations. +```c++ +const std::array a{ 1, 2, 3 }; + +std::inclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, std::plus<>{}); // 1 3 6 + +std::exclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, 0, std::plus<>{}); // 0 1 3 + +const auto times_ten = [](const auto n) { return n * 10; }; + +std::transform_inclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, std::plus<>{}, times_ten); // 10 30 60 + +std::transform_exclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, 0, std::plus<>{}, times_ten); // 0 10 30 +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index fae127b..db13925 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ C++17 includes the following new library features: - [std::sample](#stdsample) - [std::clamp](#stdclamp) - [std::reduce](#stdreduce) +- [prefix sum algorithms](#prefix-sum-algorithms) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1224,6 +1225,26 @@ std::reduce(std::cbegin(a), std::cend(a)); // == 6 std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 ``` +### Prefix sum algorithms +Support for prefix sums (both inclusive and exclusive scans) along with transformations. +```c++ +const std::array a{ 1, 2, 3 }; + +std::inclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, std::plus<>{}); // 1 3 6 + +std::exclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, 0, std::plus<>{}); // 0 1 3 + +const auto times_ten = [](const auto n) { return n * 10; }; + +std::transform_inclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, std::plus<>{}, times_ten); // 10 30 60 + +std::transform_exclusive_scan(std::cbegin(a), std::cend(a), + std::ostream_iterator{ std::cout, " " }, 0, std::plus<>{}, times_ten); // 0 10 30 +``` + ## C++14 Language Features ### Binary literals From 5a9e63549ee2d755c0061927b36ab61737aec012 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 20 Feb 2023 19:57:45 -0500 Subject: [PATCH 18/39] Add the transform examples for the std::reduce section. --- CPP17.md | 9 +++++++++ README.md | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/CPP17.md b/CPP17.md index a4b2492..07e3189 100644 --- a/CPP17.md +++ b/CPP17.md @@ -560,6 +560,15 @@ std::reduce(std::cbegin(a), std::cend(a)); // == 6 // Using a custom binary op: std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 ``` +Additionally you can specify transformations for reducers: +```c++ +std::transform_reduce(std::cbegin(a), std::cend(a), 0, std::plus<>{}, times_ten); // == 60 + +const std::array b{ 1, 2, 3 }; +const auto product_times_ten = [](const auto a, const auto b) { return a * b * 10; }; + +std::transform_reduce(std::cbegin(a), std::cend(a), std::cbegin(b), 0, std::plus<>{}, product_times_ten); // == 140 +``` ### Prefix sum algorithms Support for prefix sums (both inclusive and exclusive scans) along with transformations. diff --git a/README.md b/README.md index db13925..90f33cc 100644 --- a/README.md +++ b/README.md @@ -1224,6 +1224,15 @@ std::reduce(std::cbegin(a), std::cend(a)); // == 6 // Using a custom binary op: std::reduce(std::cbegin(a), std::cend(a), 1, std::multiplies<>{}); // == 6 ``` +Additionally you can specify transformations for reducers: +```c++ +std::transform_reduce(std::cbegin(a), std::cend(a), 0, std::plus<>{}, times_ten); // == 60 + +const std::array b{ 1, 2, 3 }; +const auto product_times_ten = [](const auto a, const auto b) { return a * b * 10; }; + +std::transform_reduce(std::cbegin(a), std::cend(a), std::cbegin(b), 0, std::plus<>{}, product_times_ten); // == 140 +``` ### Prefix sum algorithms Support for prefix sums (both inclusive and exclusive scans) along with transformations. From 2328e862399fec01ea51420bc21bc1fb16d81601 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 20 Feb 2023 20:22:40 -0500 Subject: [PATCH 19/39] GCD and LCM. --- CPP17.md | 10 ++++++++++ README.md | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/CPP17.md b/CPP17.md index 07e3189..3294986 100644 --- a/CPP17.md +++ b/CPP17.md @@ -35,6 +35,7 @@ C++17 includes the following new library features: - [std::clamp](#stdclamp) - [std::reduce](#stdreduce) - [prefix sum algorithms](#prefix-sum-algorithms) +- [gcd and lcm](#gcd-and-lcm) ## C++17 Language Features @@ -590,6 +591,15 @@ std::transform_exclusive_scan(std::cbegin(a), std::cend(a), std::ostream_iterator{ std::cout, " " }, 0, std::plus<>{}, times_ten); // 0 10 30 ``` +### GCD and LCM +Greatest common divisor (GCD) and least common multiple (LCM). +```c++ +const int p = 9; +const int q = 3; +std::gcd(p, q); // == 3 +std::lcm(p, q); // == 9 +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index 90f33cc..ead9967 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ C++17 includes the following new library features: - [std::clamp](#stdclamp) - [std::reduce](#stdreduce) - [prefix sum algorithms](#prefix-sum-algorithms) +- [gcd and lcm](#gcd-and-lcm) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1254,6 +1255,15 @@ std::transform_exclusive_scan(std::cbegin(a), std::cend(a), std::ostream_iterator{ std::cout, " " }, 0, std::plus<>{}, times_ten); // 0 10 30 ``` +### GCD and LCM +Greatest common divisor (GCD) and least common multiple (LCM). +```c++ +const int p = 9; +const int q = 3; +std::gcd(p, q); // == 3 +std::lcm(p, q); // == 9 +``` + ## C++14 Language Features ### Binary literals From c0e0f37bd00efdf208837e943f218815805a7243 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 20 Feb 2023 21:12:27 -0500 Subject: [PATCH 20/39] Add std::not_fn. --- CPP17.md | 14 ++++++++++++++ README.md | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/CPP17.md b/CPP17.md index 3294986..f0b285a 100644 --- a/CPP17.md +++ b/CPP17.md @@ -36,6 +36,7 @@ C++17 includes the following new library features: - [std::reduce](#stdreduce) - [prefix sum algorithms](#prefix-sum-algorithms) - [gcd and lcm](#gcd-and-lcm) +- [std::not_fn](#stdnot_fn) ## C++17 Language Features @@ -600,6 +601,19 @@ std::gcd(p, q); // == 3 std::lcm(p, q); // == 9 ``` +### std::not_fn +Utility function that returns the negation of the result of the given function. +```c++ +const std::ostream_iterator ostream_it{ std::cout, " " }; +const auto is_even = [](const auto n) { return n % 2 == 0; }; +std::vector v{ 0, 1, 2, 3, 4 }; + +// Print all even numbers. +std::copy_if(std::cbegin(v), std::cend(v), ostream_it, is_even); // 0 2 4 +// Print all odd (not even) numbers. +std::copy_if(std::cbegin(v), std::cend(v), ostream_it, std::not_fn(is_even)); // 1 3 +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index ead9967..7da806c 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ C++17 includes the following new library features: - [std::reduce](#stdreduce) - [prefix sum algorithms](#prefix-sum-algorithms) - [gcd and lcm](#gcd-and-lcm) +- [std::not_fn](#stdnot_fn) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1264,6 +1265,19 @@ std::gcd(p, q); // == 3 std::lcm(p, q); // == 9 ``` +### std::not_fn +Utility function that returns the negation of the result of the given function. +```c++ +const std::ostream_iterator ostream_it{ std::cout, " " }; +const auto is_even = [](const auto n) { return n % 2 == 0; }; +std::vector v{ 0, 1, 2, 3, 4 }; + +// Print all even numbers. +std::copy_if(std::cbegin(v), std::cend(v), ostream_it, is_even); // 0 2 4 +// Print all odd (not even) numbers. +std::copy_if(std::cbegin(v), std::cend(v), ostream_it, std::not_fn(is_even)); // 1 3 +``` + ## C++14 Language Features ### Binary literals From 137f8ac08a23c6743ac1c4e8bc393ab00dfa5303 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 27 Feb 2023 21:02:12 -0500 Subject: [PATCH 21/39] Add string conversion using std::to_chars and std::from_chars. --- CPP17.md | 38 ++++++++++++++++++++++++++++++++++++++ README.md | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/CPP17.md b/CPP17.md index f0b285a..26646c8 100644 --- a/CPP17.md +++ b/CPP17.md @@ -37,6 +37,7 @@ C++17 includes the following new library features: - [prefix sum algorithms](#prefix-sum-algorithms) - [gcd and lcm](#gcd-and-lcm) - [std::not_fn](#stdnot_fn) +- [string conversion to/from numbers](#string-conversion-tofrom-numbers) ## C++17 Language Features @@ -614,6 +615,43 @@ std::copy_if(std::cbegin(v), std::cend(v), ostream_it, is_even); // 0 2 4 std::copy_if(std::cbegin(v), std::cend(v), ostream_it, std::not_fn(is_even)); // 1 3 ``` +### String conversion to/from numbers +Convert 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. + +Users 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. + +These functions allow you to optionally pass a base (defaults to base-10) or a format specifier for floating type input. + +* `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. +* `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. + +Both error code objects returned from these functions are equal to the default-initialized error code object on success. + +Convert the number `123` to a `std::string`: +```c++ +const int n = 123; + +// Can use any container, string, array, etc. +std::string str; +str.resize(3); // hold enough storage for each digit of `n` + +const auto [ ptr, ec ] = std::to_chars(str.data(), str.data() + str.size(), n); + +if (ec == std::errc{}) { std::cout << str << std::endl; } // 123 +else { /* handle failure */ } +``` + +Convert from a `std::string` with value `"123"` to an integer: +```c++ +const std::string str{ "123" }; +int n; + +const auto [ ptr, ec ] = std::from_chars(str.data(), str.data() + str.size(), n); + +if (ec == std::errc{}) { std::cout << n << std::endl; } // 123 +else { /* handle failure */ } +``` + ## Acknowledgements * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. diff --git a/README.md b/README.md index 7da806c..469b798 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ C++17 includes the following new library features: - [prefix sum algorithms](#prefix-sum-algorithms) - [gcd and lcm](#gcd-and-lcm) - [std::not_fn](#stdnot_fn) +- [string conversion to/from numbers](#string-conversion-tofrom-numbers) C++14 includes the following new language features: - [binary literals](#binary-literals) @@ -1278,6 +1279,43 @@ std::copy_if(std::cbegin(v), std::cend(v), ostream_it, is_even); // 0 2 4 std::copy_if(std::cbegin(v), std::cend(v), ostream_it, std::not_fn(is_even)); // 1 3 ``` +### String conversion to/from numbers +Convert 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. + +Users 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. + +These functions allow you to optionally pass a base (defaults to base-10) or a format specifier for floating type input. + +* `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. +* `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. + +Both error code objects returned from these functions are equal to the default-initialized error code object on success. + +Convert the number `123` to a `std::string`: +```c++ +const int n = 123; + +// Can use any container, string, array, etc. +std::string str; +str.resize(3); // hold enough storage for each digit of `n` + +const auto [ ptr, ec ] = std::to_chars(str.data(), str.data() + str.size(), n); + +if (ec == std::errc{}) { std::cout << str << std::endl; } // 123 +else { /* handle failure */ } +``` + +Convert from a `std::string` with value `"123"` to an integer: +```c++ +const std::string str{ "123" }; +int n; + +const auto [ ptr, ec ] = std::from_chars(str.data(), str.data() + str.size(), n); + +if (ec == std::errc{}) { std::cout << n << std::endl; } // 123 +else { /* handle failure */ } +``` + ## C++14 Language Features ### Binary literals From 2b2ebe64b357a6bd2f01531bb4bde0731018eb50 Mon Sep 17 00:00:00 2001 From: Anthony Calandra Date: Mon, 27 Feb 2023 21:41:12 -0500 Subject: [PATCH 22/39] Add CTAD. --- CPP17.md | 34 ++++++++++++++++++++++++++++++++++ README.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/CPP17.md b/CPP17.md index 26646c8..f26c059 100644 --- a/CPP17.md +++ b/CPP17.md @@ -19,6 +19,7 @@ C++17 includes the following new language features: - [direct-list-initialization of enums](#direct-list-initialization-of-enums) - [\[\[fallthrough\]\], \[\[nodiscard\]\], \[\[maybe_unused\]\] attributes](#fallthrough-nodiscard-maybe_unused-attributes) - [\_\_has\_include](#\_\_has\_include) +- [class template argument deduction](#class-template-argument-deduction) C++17 includes the following new library features: - [std::variant](#stdvariant) @@ -360,6 +361,39 @@ It can also be used to include headers existing under different names or locatio #endif ``` +### Class template argument deduction +*Class template argument deduction* (CTAD) allows the compiler to deduce template arguments from constructor arguments. +```c++ +std::vector v{ 1, 2, 3 }; // deduces std::vector + +std::mutex mtx; +auto lck = std::lock_guard{ mtx }; // deduces to std::lock_guard + +auto p = new std::pair{ 1.0, 2.0 }; // deduces to std::pair +``` + +For user-defined types, *deduction guides* can be used to guide the compiler how to deduce template arguments if applicable: +```c++ +template +struct container { + container(T t) {} + + template + container(Iter beg, Iter end); +}; + +// deduction guide +template