From 1343f5eeef4c41b19b6f7e68d75000758ed1f476 Mon Sep 17 00:00:00 2001 From: Chengqi Deng Date: Sat, 4 Dec 2021 07:48:04 +0800 Subject: [PATCH] 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