diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..2957eb0e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [changkun] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000..2c6b76cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,49 @@ +--- +name: Bug report +about: 报告错误 + +--- + + + +## Actual Description + +- File Path: for example, `book/en-us/02-usability.md` +- Original paragraph: + +``` +A copy of the original paragraph +``` + +## Expected Description + +``` +A modified paragraph +``` + +## Attachments + +Attach screenshot or files if necessary. + +--- + + + +## 实际描述 + +- 文件路径:例如,book/zh-cn/02-usability.md +- 原文段落: + +``` +复制原文段落 +``` + +## 预期描述 + +``` +修改后的段落 +``` + +## 附图 + +必要时,请附上相关截图 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 00000000..470e91ba --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,27 @@ +--- +name: Feature request +about: 内容建议 + +--- + + + +## Motivation + +Please briefly describe your motivation. + +## Requirements + +Please list all of your suggestions. + +--- + + + +## 动机 + +请描述你提交内容建议的动机。 + +## 需求说明 + +请描述你提交内容建议的详单,例如具体是增加哪个知识点的说明。 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md new file mode 100644 index 00000000..0c13fb73 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -0,0 +1,19 @@ +--- +name: Question +about: 提交问题 + +--- + + + +## Question + +Please describe your question here, and read [How-To-Ask-Questions-The-Smart-Way](http://www.catb.org/~esr/faqs/smart-questions.html) before you submit your question. + +--- + + + +## 问题描述 + +请在此描述你的问题,提问前请参考[提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md) \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..29c3aa7b --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,35 @@ +resolve #issue_id + + + +## Description + +Please describe the motivation of this pull request, and what problem was solved in this PR. + +## Change List + +- Fix typo error of XXX +- Add description regarding XXX feature +- Resolve error content of XXX + +## Reference + +Please add reference if necessary + +--- + + + +## 说明 + +此处详细说明 PR 的动机是什么、解决了什么样的问题。 + +## 变化箱单 + +- 修复了 XXX 的 typo 错误 +- 增加了 XXX 相关的说明 +- 解决了关于 XXX 的描述性错误 + +## 参考文献 + +如果有请注明 \ No newline at end of file diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml new file mode 100644 index 00000000..a9d7187d --- /dev/null +++ b/.github/workflows/website.yml @@ -0,0 +1,29 @@ +name: Website + +on: + push: + branches: [ master ] + +jobs: + + build: + name: Website + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v2 + - name: build + env: + USER: ${{ secrets.SERVER_USER }} + TARGET: ${{ secrets.SERVER_PATH }} + KEY: ${{ secrets.SERVER_KEY }} + DOMAIN: ${{ secrets.SERVER_DOMAIN }} + run: | + make build + mkdir ~/.ssh + echo "$KEY" | tr -d '\r'> ~/.ssh/id_ed25519 + chmod 400 ~/.ssh/id_ed25519 + eval "$(ssh-agent -s)" + ssh-add ~/.ssh/id_ed25519 + ssh-keyscan -H $DOMAIN>> ~/.ssh/known_hosts + scp -r website/public/modern-cpp/* $USER@$DOMAIN:$TARGET \ No newline at end of file diff --git a/.gitignore b/.gitignore index 5f81c8a8..f6224793 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,15 @@ pdf/zh-cn/*.md website/db.json website/public/* -website/src/modern-cpp/book/* +website/src/modern-cpp/zh-cn/* +website/src/modern-cpp/en-us/* +website/src/modern-cpp/exercises +website/src/modern-cpp/code +website/src/modern-cpp/about/donate.md +website/src/modern-cpp/assets/alipay.jpg +website/src/modern-cpp/assets/cover-2nd-en.png website/src/modern-cpp/assets/cover-2nd.png -website/src/modern-cpp/assets/figures/* \ No newline at end of file +website/src/modern-cpp/assets/cover-2nd-en-logo.png +website/src/modern-cpp/assets/cover-2nd-logo.png +website/src/modern-cpp/assets/figures/* +website/src/modern-cpp/assets/wechat.jpg diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..eaf83cd9 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at hi at changkun dot us. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..054bc2ad --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,71 @@ +# How to contribute + +## Submit Issue + +C++ 11/14/17 issue is used to track the principle description error, `typo` error, and the questions to the author of the book. + +- Usually, you may encounter typos, semantic errors, grammatical errors, and etc. These are all `typo` errors. If an error has caused some obstacles to your reading and you strongly believe that the `typo` will also affect others reading, then you are very welcome to [submit issue](https://github.com/changkun/modern-cpp-tutorial/issues) to report the `typo` error. + +- Do not hesitate to submit a `principle` error because it will prevent wrong knowledge being spread. +Report the error immediately by [submitting issue](https://github.com/changkun/modern-cpp-tutorial/issues) to avoid the propogation of wrong knowledge. + +- If you found some part of the book confusing, you are very welcome to [submit an issue](https://github.com/changkun/modern-cpp-tutorial/issues) for asking questions. + +- The book cannot cover the entirety C++ of course, however, you are very welcome to [submit an issue](https://github.com/changkun/modern-cpp-tutorial/issues) with a suggestion if you find some important feature is missing in the book. + +## Pull Request + +"C++ 11/14/17 On the Fly" is open source so that everyone can contribute to contribute via a PR. However, it is required to read the following instructions carefully before submitting your pull request: + +- Before you submit your pull request, make sure that the [issue list](https://github.com/changkun/modern-cpp-tutorial/issues) already contains the problem you want to solve. If not, please refer to the **Submit Issue** section. + +- Make sure your PR has improved more than 50 `typo` errors, otherwise please do not submit a PR. + +- For a PR that fixes principled errors, please don't hesitate, all of the readers of the book are very grateful for your contribution! + +- If you would like to be a co-author of this book, please send an email to ask: `hi at changkun dot us`. + +Since this repository provides a variety of reading approaches, thus make sure you have checked all items in the following checklist: + +- [ ] If you only making changes to the main part of the book (i.e. the `book` folder), and no changes to the code snippet, then you are good to go; +- [ ] If you also changed the code snippet in the main body of the book, then you need to synchronize the corresponding code snippet in the `code` folder; +- [ ] If your changes also involve the exercises, you also need to synchronize the contents of the `exercises` folder. + +# 如何参与贡献 + +## 提交 Issue + +『C++ 11/14/17/20』的 issue 用于追踪书中存在的原则性的描述错误、存在的 `typo` 错误,以及向本书作者提问等。 + +- 通常情况下,你可能会发现书中某个段落存在错别字、语义错误、文法错误等。 +这都是 `typo` 错误。如果该错误已经对你的阅读造成了一定障碍, +你也强烈的认为该 `typo` 也会影响到其他人的阅读, +那么非常欢迎[提交 issue](https://github.com/changkun/modern-cpp-tutorial/issues) +来报告 `typo` 错误。 + +- 对于书中存在的原则性错误,例如对源码进行分析的内容产生明显的错误、 +且内容对其他人会产生严重的误导,请不要犹豫, +立即[提交 issue](https://github.com/changkun/modern-cpp-tutorial/issues) 来报告此错误,以免继续传播错误的知识。 +如果可以,也请附上相关改进说明。通常情况下,如果存在这类问题,我们鼓励你一并提交改进 PR。 + +- 如果你在阅读本书的时候发现有部分内容难于理解,也欢迎[提交 issue](https://github.com/changkun/modern-cpp-tutorial/issues) 来询问作者表达你的疑惑。 +作者会根据实际情况重新优化这一部分的内容,进而帮助他人更易阅读这部分的内容。 + +- 我们也欢迎你提交针对本书内容的相关建议,具体来说如果你认为书中未涉及的某个模块或者文件的源码值得讨论,也欢迎 [提交 issue](https://github.com/changkun/go-under-the-hood/issues) 来进一步讨论。 + +## 提交 Pull request + +『C++ 11/14/17/20』是一本开源书籍,任何人都可以参与贡献自己 PR。但在提交 PR 之前请仔细阅读下面的说明: + +- 当你认为需要提交一个 PR 时,请确保 [issue 列表](https://github.com/changkun/modern-cpp-tutorial/issues)中,已经包含了你想要解决的问题。 +如果没有,请参考**提交 Issue** 一节中的描述,提交你的 issue,再提交你的 PR。 + +- 当你准备提交一个 typo 错误的 PR 时,请确保你的 PR 改进了 **超过 50 个汉字(或英文单词)** 的 `typo` 错误,否则请不要提交 PR。 +- 对于一个修复原则性错误的 PR,请不要犹豫,笔者对此表示非常感谢! +- 如果非常喜欢本书,以至于希望参与本书的合著,成为作者,请发邮件询问:`hi at changkun dot us`。 + +本仓库提供了多种阅读方式,如果你提交一个 Pull request,则请确保你检查的如下的 checklist: + +- [ ] 只改动原书正文 `book` 下的部分内容,不涉及代码片段的修改,则无需进行修改 +- [ ] 如果同时还改动了正文中的代码片段,则需要同步 `code` 文件夹下对应的代码片段 +- [ ] 如果改动还涉及习题的设计,则需要同步 `exercises` 文件夹下的内容 diff --git a/LICENSE b/LICENSE index 57e96434..3800ec13 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 - Present Changkun Ou +Copyright (c) 2016 - 2020 Changkun Ou Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 5bc73e65..f957a0de 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,31 @@ -all: pdf website +NAME=modern-cpp-tutorial +DOCKER_ENV=changkun/$(NAME):build-env +TARGET = pdf epub +LANGS = zh-cn en-us +ALL_BUILDS = website $(TARGET) -pdf: - cd pdf/zh-cn && make - cd pdf/en-us && make +# dep + +all: $(ALL_BUILDS) + +$(TARGET): $(LANGS) + mkdir -p website/public/modern-cpp/$@/ + for lang in $^ ; do \ + cd $@/$${lang} && make && make clean && cd ../..; \ + mv $@/$${lang}/$(NAME).$@ website/public/modern-cpp/$@/$(NAME)-$${lang}.$@; \ + done website: cd website && make +build: + docker run --rm -v `pwd`:/$(NAME) $(DOCKER_ENV) make + +# dev + +build-env: + docker build -t $(DOCKER_ENV) -f ./docker/Dockerfile . + serve: cd website && make s @@ -14,5 +33,7 @@ clean: cd pdf/zh-cn && make clean cd pdf/en-us && make clean cd website && make clean + docker images -f "dangling=true" -q | xargs docker rmi -f + docker image prune -f -.PHONY : pdf website clean \ No newline at end of file +.PHONY : $(LANGS) $(ALL_BUILDS) serve build-env build-all clean \ No newline at end of file diff --git a/README-en-us.md b/README-en-us.md deleted file mode 100644 index 495ef8e4..00000000 --- a/README-en-us.md +++ /dev/null @@ -1,54 +0,0 @@ -logo - -# C++11/14/17 On the Fly - -![](https://img.shields.io/badge/version-v2-green.svg) [![](https://img.shields.io/badge/language-%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-red.svg)](./README.md) [![](https://img.shields.io/badge/language-English-blue.svg)](./README-en-us.md) [![](https://img.shields.io/badge/$-donate-ff69b4.svg)](./assets/donate.md) [![](https://img.shields.io/badge/chat-community-667ed5.svg)](./assets/community.md) - - -> This book is adapting to C++17 and translating to English. - -## Purpose - -The book claims "On the Fly". Its intent is to provide a comprehensive introduction to the relevant features regarding modern C++ (before 2020s). -Readers can choose interesting content according to the following table of content to learn and quickly familiarize the new features you would like to learn. -Readers should aware that all of these features are not required. It should be leart when you really need it. - -At the same time, instead of grammar-only, the book introduces the historical background as simple as possible of its technical requirements, which provides great help in understanding why these features comes out. - -In addition, The author would like to encourage that readers should be able to use C++17 directly in their new projects and migrate their old projects to C++17 gradually after read the book. - -## Targets - -- This book assumes that readers are already familiar with traditional C++ (e.g. C++98), at least they do not have any difficulty in reading traditional C++ code. In other words, those who have long experience in traditional C++ and people who desire to quickly understand the features of modern C++ in a short period of time are well suited to read the book; - -- This book introduces to a certain extent of the dark magic of modern C++. However, these magics are very limited, they are not suitable for readers who want to learn advanced C++. The purpose of this book is offering a quick start for modern C++. Of course, advanced readers can also use this book to review and examine themselves on modern C++. - -## Start - -You can choose from the following reading methods: - -- [GitHub Online](./book/en-us/toc.md) -- [PDF document](./pdf/en-us/modern-cpp-tutorial.pdf) -- [Website](https://changkun.de/modern-cpp) - -## Code - -Each chapter of this book has a lot of code. If you encounter problems when writing your own code with the introductory features of the book, you might as well read the source code attached to the book. You can find the book [here](./code). All the code organized by chapter, the folder name is the chapter number. - -## Exercises - -There are few exercises At the end of each chapter of the book. It is for testing whether you can use the knowledge points in the current chapter. You can find the possible answer to the problem from [here](./exercise). The folder name is the chapter number. - -## Website - -The source code of the [website](https://changkun.de/modern-cpp) of this book can be found [here](./website), which is built by [hexo](https://hexo.io) and [vuejs](https://vuejs.org). The website provides you another way of reading the book, it is also adapts to mobile. - -## Acknowledgements - -This book is originally written in Chinese. - -The author has limited time and language skills. If readers find any mistakes of the book or any language improvements, please feel free to open an [Issue](https://github.com/changkun/modern-cpp-tutorial/issues) or start a [Pull request](https://github.com/changkun/modern-cpp-tutorial/pulls). - -## Licenses - -Creative Commons License
This work is written by [Ou Changkun](https://changkun.de) and licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. The code of this repository is open sourced under the [MIT license](./LICENSE). \ No newline at end of file diff --git a/README-zh-cn.md b/README-zh-cn.md new file mode 100644 index 00000000..4b06afa7 --- /dev/null +++ b/README-zh-cn.md @@ -0,0 +1,64 @@ +logo + +# 现代 C++ 教程:高速上手 C++11/14/17/20 + +![](https://img.shields.io/travis/changkun/modern-cpp-tutorial/master?style=flat-square) [![](https://img.shields.io/badge/language-English-blue.svg?style=flat-square)](./README.md) [![](https://img.shields.io/badge/language-简体中文-red.svg?style=flat-square)](./README-zh-cn.md) [![](https://img.shields.io/badge/€-donate-ff69b4.svg?style=flat-square)](./assets/donate.md) + +## 本书目的 + +本书号称『高速上手』,从内容上对二十一世纪二十年代之前产生 C++ 的相关特性做了非常相对全面的介绍,读者可以自行根据下面的目录选取感兴趣的内容进行学习,快速熟悉需要了解的内容。这些特性并不需要全部掌握,只需针对自己的使用需求和特定的应用场景,学习、查阅最适合自己的新特性即可。 + +同时,本书在介绍这些特性的过程中,尽可能简单明了的介绍了这些特性产生的历史背景和技术需求,这为理解这些特性、运用这些特性提供了很大的帮助。 + +此外,笔者希望读者在阅读本书后,能够努力在新项目中直接使用现代 C++,并努力将旧项目逐步迁移到现代 C++。也算是笔者为推进现代 C++ 的普及贡献了一些绵薄之力。 + +## 目标读者 + +1. 本书假定读者已经熟悉了传统 C++ ,至少在阅读传统 C++ 代码上不具备任何困难。换句话说,那些长期使用传统 C++进行编码的人、渴望在短时间内迅速了解**现代 C++** 特性的人非常适合阅读本书; +2. 本书一定程度上介绍了一些现代 C++ 的**黑魔法**,但这些魔法毕竟有限,不适合希望进阶学习现代 C++ 的读者,本书的定位系**现代 C++ 的快速上手**。当然,希望进阶学习的读者可以使用本书来回顾并检验自己对 **现代 C++** 的熟悉度。 + +## 开始阅读 + +你可以选择以下几种阅读方式: + +1. [GitHub 在线](./book/zh-cn/toc.md) +2. [PDF 文档](https://changkun.de/modern-cpp/pdf/modern-cpp-tutorial-zh-cn.pdf) +3. [EPUB 文档](https://changkun.de/modern-cpp/epub/modern-cpp-tutorial-zh-cn.epub) +4. [网站](https://changkun.de/modern-cpp/) + +## 相关代码 + +本书每章中都出现了大量的代码,如果你在跟随本书介绍特性的思路编写自己的代码遇到问题时,不妨读一读随书附上的源码,你可以在[这里](./code)中找到书中介绍过的全部的源码,所有代码按章节组织,文件夹名称为章节序号。 + +## 随书习题 + +本书每章最后还加入了少量难度极小的习题,仅用于检验你是否能混合运用当前章节中的知识点。你可以在[这里](./exercises)找到习题的答案,文件夹名称为章节序号。 + +## 本书网站 + +本书的[网站](https://changkun.de/modern-cpp)源码可以在[这里](./website)找到,由 [hexo](https://hexo.io) 和 [vuejs](https://vuejs.org) 协同构建而成。网站旨在提供一个除 GitHub 之外的阅读方式,除了在桌面端访问之外,你也可以在移动端上阅读本书。 + +## 构建 + +如果你希望在本地编译整个仓库,我们建议使用 [Docker](https://docs.docker.com/install/)。如果 Docker 在你的本地能正常使用,则可以简单的通过运行下面的指令完成构建: + +```bash +$ make build +``` + +## 致谢 + +笔者时间和水平有限,如果读者发现书中内容的错误,欢迎提 [Issue](https://github.com/changkun/modern-cpp-tutorial/issues),或者直接提 [Pull request](https://github.com/changkun/modern-cpp-tutorial/pulls)。详细贡献指南请参考[如何参与贡献](CONTRIBUTING.md),由衷感谢每一位指出本书中出现错误的读者,包括但不限于 [Contributors](https://github.com/changkun/modern-cpp-tutorial/graphs/contributors)。 + +

本项目还由以下产品提供赞助支持:

+

+ + + +

+ +## 许可 + +知识共享许可协议 + +本书系[欧长坤](https://github.com/changkun)著,采用[知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议](https://creativecommons.org/licenses/by-nc-nd/4.0/)许可。项目中代码使用 MIT 协议开源,参见[许可](./LICENSE)。 diff --git a/README.md b/README.md index 38b46307..45df2bec 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,68 @@ -logo +logo -# 《高速上手 C++11/14/17》 +# Modern C++ Tutorial: C++11/14/17/20 On the Fly -![](https://img.shields.io/badge/version-v2-green.svg) -[![](https://img.shields.io/badge/language-%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87-red.svg)](./README.md) [![](https://img.shields.io/badge/language-English-blue.svg)](./README-en-us.md) -[![](https://img.shields.io/badge/%C2%A5-%E8%B5%9E%E5%8A%A9-ff69b4.svg)](./assets/donate.md) -[![](https://img.shields.io/badge/chat-%E4%BA%A4%E6%B5%81-667ed5.svg)](./assets/community.md) +![](https://img.shields.io/travis/changkun/modern-cpp-tutorial/master?style=flat-square) [![](https://img.shields.io/badge/language-English-blue.svg?style=flat-square)](./README.md) [![](https://img.shields.io/badge/language-简体中文-red.svg?style=flat-square)](./README-zh-cn.md) [![](https://img.shields.io/badge/€-donate-ff69b4.svg?style=flat-square)](./assets/donate.md) +## Purpose -> 本书正在适配 C++17 新特性,尽请期待。 +The book claims to be "On the Fly". Its intent is to provide a comprehensive introduction to the relevant features regarding modern C++ (before 2020s). +Readers can choose interesting content according to the following table of content to learn and quickly familiarize the new features you would like to learn. +Readers should be aware that not all of these features are required. Instead, it should be learned when you really need it. -## 本书目的 +At the same time, instead of coding-only, the book introduces the historical background of its technical requirements (as simple as possible), which provides great help in understanding why these features came out. -本书号称『高速上手』,从内容上对二十一世纪二十年代之前产生 C++ 的相关特性做了非常相对全面的介绍,读者可以自行根据下面的目录选取感兴趣的内容进行学习,快速熟悉需要了解的内容。这些特性并不需要全部掌握,只需针对自己的使用需求和特定的应用场景,学习、查阅最适合自己的新特性即可。 +In addition, the author would like to encourage readers to use modern C++ directly in their new projects and migrate their old projects to modern C++ gradually after reading the book. -同时,本书在介绍这些特性的过程中,尽可能简单明了的介绍了这些特性产生的历史背景和技术需求,这为理解这些特性、运用这些特性提供了很大的帮助。 +## Targets -此外,笔者希望读者在阅读本书后,能够努力在新项目中直接使用 C++17,并努力将旧项目逐步迁移到 C++17。也算是笔者为推进现代 C++ 的普及贡献了一些绵薄之力。 +- This book assumes that readers are already familiar with traditional C++ (i.e. C++98 or earlier), or at least that they do not have any difficulty in reading traditional C++ code. In other words, those who have long experience in traditional C++ and people who desire to quickly understand the features of modern C++ in a short period of time are well suited to read the book. -## 目标读者 +- This book introduces, to a certain extent, the dark magic of modern C++. However, these magic tricks are very limited, they are not suitable for readers who want to learn advanced C++. The purpose of this book is offering a quick start for modern C++. Of course, advanced readers can also use this book to review and examine themselves on modern C++. -1. 本书假定读者已经熟悉了传统 C++ ,至少在阅读传统 C++ 代码上不具备任何困难。换句话说,那些长期使用传统 C++进行编码的人、渴望在短时间内迅速了解**现代 C++** 特性的人非常适合阅读本书; -2. 本书一定程度上介绍了一些现代 C++ 的**黑魔法**,但这些魔法毕竟有限,不适合希望进阶学习现代 C++ 的读者,本书的定位系**现代 C++ 的快速上手**。当然,希望进阶学习的读者可以使用本书来回顾并检验自己对 **现代 C++** 的熟悉度。 +## Start -## 开始阅读 +You can choose from the following reading methods: -你可以选择以下几种阅读方式: +- [GitHub Online](./book/en-us/toc.md) +- [PDF document](https://changkun.de/modern-cpp/pdf/modern-cpp-tutorial-en-us.pdf) +- [EPUB document](https://changkun.de/modern-cpp/epub/modern-cpp-tutorial-en-us.epub) +- [Website](https://changkun.de/modern-cpp) -1. [GitHub 在线](./book/zh-cn/toc.md) -2. [PDF 文档](./pdf/zh-cn/modern-cpp-tutorial.pdf) -3. [网站](https://changkun.de/modern-cpp/) +## Code -## 相关代码 +Each chapter of this book contains a lot of code. If you encounter problems while writing your own code with the introductory features of the book, reading the source code attached to the book might be of help. You can find the book [here](./code). All the code is organized by chapter, the folder name is the chapter number. -本书每章中都出现了大量的代码,如果你在跟随本书介绍特性的思路编写自己的代码遇到问题时,不妨读一读随书附上的源码,你可以在[这里](./code)中找到书中介绍过的全部的源码,所有代码按章节组织,文件夹名称为章节序号。 +## Exercises -## 随书习题 +There are few exercises at the end of each chapter of the book. These are meant to test whether you have mastered the knowledge in the current chapter. You can find the possible answer to the problem [here](./exercises). Again, the folder name is the chapter number. -本书每章最后还加入了少量难度极小的习题,仅用于检验你是否能混合运用当前章节中的知识点。你可以在[这里](exercises)找到习题的答案,文件夹名称为章节序号。 +## Website -## 本书网站 +The source code of the [website](https://changkun.de/modern-cpp) of this book can be found [here](./website), which is built by [hexo](https://hexo.io) and [vuejs](https://vuejs.org). The website provides you another way of reading the book, it also adapts to mobile browsers. -本书的[网站](https://changkun.de/modern-cpp)源码可以在[这里](./website)找到,由 [hexo](https://hexo.io) 和 [vuejs](https://vuejs.org) 协同构建而成。网站旨在提供一个除 GitHub 之外的阅读方式,除了在桌面端访问之外,你也可以在移动端上阅读本书。 +## Build -## 致谢 +If you are interested in building everything locally, it is recommended using [Docker](https://docs.docker.com/install/). To build, simply run: -笔者时间和水平有限,如果读者发现书中内容的错误,欢迎提 [Issue](https://github.com/changkun/modern-cpp-tutorial/issues),或者直接提 [Pull request](https://github.com/changkun/modern-cpp-tutorial/pulls)。由衷感谢每一位指出本书中出现错误的读者。 +```bash +$ make build +``` -## 许可 +## Acknowledgements -知识共享许可协议 +This book was originally written in Chinese by [Changkun Ou](https://changkun.de). -本书系[欧长坤](https://github.com/changkun)著,采用[知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议](http://creativecommons.org/licenses/by-nc-nd/4.0/)许可。项目中代码使用 MIT 协议开源,参见[许可](./LICENSE)。 +The author has limited time and language skills. If readers find any mistakes in the book or any language improvements, please feel free to open an [Issue](https://github.com/changkun/modern-cpp-tutorial/issues) or start a [Pull request](https://github.com/changkun/modern-cpp-tutorial/pulls). For detailed guidelines and checklist, please refer to [How to contribute](CONTRIBUTING.md). + +The author is grateful to all contributors, including but not limited to [Contributors](https://github.com/changkun/modern-cpp-tutorial/graphs/contributors). + +

This project is also supported by:

+

+ + + +

+ +## Licenses + +Creative Commons License
This work was written by [Ou Changkun](https://changkun.de) and licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. The code of this repository is open sourced under the [MIT license](./LICENSE). diff --git a/assets/community-international.md b/assets/community-international.md deleted file mode 100644 index 3969644e..00000000 --- a/assets/community-international.md +++ /dev/null @@ -1,5 +0,0 @@ -# Community - -This book offers a reader community, you can join this Telegram: - -TBA \ No newline at end of file diff --git a/assets/community.md b/assets/community.md deleted file mode 100644 index 76e2707a..00000000 --- a/assets/community.md +++ /dev/null @@ -1,7 +0,0 @@ -# 交流 - -本书有以下读者交流群,有兴趣的读者可以加入,加群需正确回答加群密码: - -![](qq-group.png) - -> 提示: `bW9kZXJuLWNwcC10dXRvcmlhbC1naXRodWI=` diff --git a/assets/cover-2nd-en-logo.png b/assets/cover-2nd-en-logo.png new file mode 100644 index 00000000..050a18e0 Binary files /dev/null and b/assets/cover-2nd-en-logo.png differ diff --git a/assets/cover-2nd-en.afphoto b/assets/cover-2nd-en.afphoto index 8e0de941..60d66375 100644 Binary files a/assets/cover-2nd-en.afphoto and b/assets/cover-2nd-en.afphoto differ diff --git a/assets/cover-2nd-en.png b/assets/cover-2nd-en.png index cae0dadd..3811060d 100644 Binary files a/assets/cover-2nd-en.png and b/assets/cover-2nd-en.png differ diff --git a/assets/cover-2nd-logo.png b/assets/cover-2nd-logo.png new file mode 100644 index 00000000..a05a42a1 Binary files /dev/null and b/assets/cover-2nd-logo.png differ diff --git a/assets/cover-2nd.afphoto b/assets/cover-2nd.afphoto new file mode 100644 index 00000000..a313ae3a Binary files /dev/null and b/assets/cover-2nd.afphoto differ diff --git a/assets/cover-2nd.png b/assets/cover-2nd.png index 92ea730f..c89122bb 100644 Binary files a/assets/cover-2nd.png and b/assets/cover-2nd.png differ diff --git a/assets/donate-international.md b/assets/donate-international.md deleted file mode 100644 index ff1e837b..00000000 --- a/assets/donate-international.md +++ /dev/null @@ -1,5 +0,0 @@ -# Donate - -To donate the author: - -TBA \ No newline at end of file diff --git a/assets/donate.md b/assets/donate.md index e71fb0fe..88ca78d1 100644 --- a/assets/donate.md +++ b/assets/donate.md @@ -1,7 +1,20 @@ -# 赞助 +--- +title: 资助 +type: about +order: 1 +--- + +## Donate + +I would love if you support me to make the book better: + +[![](https://img.shields.io/badge/donate-PayPal-104098.svg?style=popout-square&logo=PayPal)](https://www.paypal.me/changkunde/4.99eur) + +## 资助 如果你认为本书对你起到了帮助,并希望赞助作者,可以通过下面的二维码给予支持: |微信|支付宝| |:--:|:--:| -|![](wechat.jpg) | ![](alipay.jpg)| \ No newline at end of file +|![](../assets/wechat.jpg) | ![](../assets/alipay.jpg)| + diff --git a/assets/figures/pointers1_en.png b/assets/figures/pointers1_en.png new file mode 100644 index 00000000..6a96338f Binary files /dev/null and b/assets/figures/pointers1_en.png differ diff --git a/assets/qq-group.png b/assets/qq-group.png deleted file mode 100644 index c567cd76..00000000 Binary files a/assets/qq-group.png and /dev/null differ diff --git a/book/en-us/00-preface.md b/book/en-us/00-preface.md new file mode 100644 index 00000000..b93705a3 --- /dev/null +++ b/book/en-us/00-preface.md @@ -0,0 +1,52 @@ +--- +title: Preface +type: book-en-us +order: 0 +--- + +# Preface + +[TOC] + +## Introduction + +The C++ programming language owns a fairly large user group. From the advent of C++98 to the official finalization of C++11, it has continued to stay relevant. C++14/17 is an important complement and optimization for C++11, and C++20 brings this language to the door of modernization. The extended features of all these new standards are integrated into the C++ language and infuse it with new vitality. +C++ programmers who are still using **traditional C++** (this book refers to C++98 and its previous standards as traditional C++) may even amazed by the fact that they are not using the same language while reading modern C++ code. + +**Modern C++** (this book refers to C++11/14/17/20) introduces many features into traditional C++ which bring the entire language to a new level of modernization. Modern C++ not only enhances the usability of the C++ language itself, but the modification of the `auto` keyword semantics gives us more confidence in manipulating extremely complex template types. At the same time, a lot of enhancements have been made to the language runtime. The emergence of Lambda expressions has given C++ the "closure" feature of "anonymous functions", which are in almost all modern programming languages ​​(such as Python, Swift, etc). It has become commonplace, and the emergence of rvalue references has solved the problem of temporary object efficiency that C++ has long been criticized for. + +C++17 is the direction that has been promoted by the C++ community in the past three years. It also points out an important development direction of **modern C++** programming. Although it does not appear as much as C++11, it contains a large number of small and beautiful languages ​​and features (such as structured binding), and the appearance of these features once again corrects our programming paradigm in C++. + +Modern C++ also adds a lot of tools and methods to its standard library such as `std::thread` at the level of the language itself, which supports concurrent programming and no longer depends on the underlying system on different platforms. The API implements cross-platform support at the language level; `std::regex` provides full regular expression support and more. C++98 has been proven to be a very successful "paradigm", and the emergence of modern C++ further promotes this paradigm, making C++ a better language for system programming and library development. Concepts verify the compile-time of template parameters, further enhancing the usability of the language. + +In conclusion, as an advocate and practitioner of C++, we always maintain an open mind to accept new things, and we can promote the development of C++ faster, making this old and novel language more vibrant. + +## Targets + +- This book assumes that readers are already familiar with traditional C++ (i.e. C++98 or earlier), at least they do not have any difficulty in reading traditional C++ code. In other words, those who have long experience in traditional C++ and people who desire to quickly understand the features of modern C++ in a short period are well suited to read the book; + +- This book introduces to a certain extent of the dark magic of modern C++. However, these magics are very limited, they are not suitable for readers who want to learn advanced C++. The purpose of this book is to offer a quick start for modern C++. Of course, advanced readers can also use this book to review and examine themselves on modern C++. + +## Purpose + +The book claims "On the Fly". It intends to provide a comprehensive introduction to the relevant features regarding modern C++ (before the 2020s). +Readers can choose interesting content according to the following table of contents to learn and quickly familiarize themselves with the new features that are available. +Readers should aware that all of these features are not required. It should be learned when you need it. + +At the same time, instead of grammar-only, the book introduces the historical background as simple as possible of its technical requirements, which provides great help in understanding why these features come out. + +Also, the author would like to encourage that readers should be able to use modern C++ directly in their new projects and migrate their old projects to modern C++ gradually after reading the book. + +## Code + +Each chapter of this book has a lot of code. If you encounter problems when writing your own code with the introductory features of the book, you might as well read the source code attached to the book. You can find the book [here](../../code). All the code is organized by chapter, the folder name is the chapter number. + +## Exercises + +There are few exercises At the end of each chapter of the book. It is for testing whether you can use the knowledge points in the current chapter. You can find the possible answer to the problem from [here](../../exercise). The folder name is the chapter number. + +[Table of Content](./toc.md) | [Next Chapter: Towards Modern C++](./01-intro.md) + +## Licenses + +Creative Commons License
This work was written by [Ou Changkun](https://changkun.de) and licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. The code of this repository is open sourced under the [MIT license](../../LICENSE). diff --git a/book/en-us/01-intro.md b/book/en-us/01-intro.md new file mode 100644 index 00000000..03ecd88c --- /dev/null +++ b/book/en-us/01-intro.md @@ -0,0 +1,149 @@ +--- +title: "Chapter 01: Towards Modern C++" +type: book-en-us +order: 1 +--- + +# Chapter 01: Towards Modern C++ + +[TOC] + +**Compilation Environment**: This book will use `clang++` as the only compiler used, +and always use the `-std=c++2a` compilation flag in your code. + +```bash +> clang++ -v +Apple LLVM version 10.0.1 (clang-1001046.4) +Target: x86_64-apple-darwin18.6.0 +Thread model: posix +InstalledDir: /Library/Developer/CommandLineTools/usr/bin +``` + +## 1.1 Deprecated Features + +Before learning modern C++, let's take a look at the main features that have deprecated since C++11: + +> **Note**: Deprecation is not completely unusable, it is only intended to imply that features will disappear from future standards and should be avoided. But, the deprecated features are still part of the standard library, and most of the features are actually "permanently" reserved for compatibility reasons. + +- **The string literal constant is no longer allowed to be assigned to a `char *`. If you need to assign and initialize a `char *` with a string literal constant, you should use `const char *` or `auto`.** + + ```cpp + char *str = "hello world!"; // A deprecation warning will appear + ``` + +- **C++98 exception description, `unexpected_handler`, `set_unexpected()` and other related features are deprecated and should use `noexcept`.** + +- **`auto_ptr` is deprecated and `unique_ptr` should be used.** + +- **`register` keyword is deprecated and can be used but no longer has any practical meaning.** + +- **The `++` operation of the `bool` type is deprecated.** + +- **If a class has a destructor, the properties for which it generates copy constructors and copy assignment operators are deprecated.** + +- **C language style type conversion is deprecated (ie using `(convert_type)`) before variables, and `static_cast`, `reinterpret_cast`, `const_cast` should be used for type conversion.** + +- **In particular, some of the C standard libraries that can be used are deprecated in the latest C++17 standard, such as ``, ``, `` and `` etc.** + +- ... and many more + +There are also other features such as parameter binding (C++11 provides `std::bind` and `std::function`), `export` etc. are also deprecated. These features mentioned above **If you have never used or heard of it, please don't try to understand them. You should move closer to the new standard and learn new features directly**. After all, technology is moving forward. + +## 1.2 Compatibilities with C + +For some force majeure and historical reasons, we had to use some C code (even old C code) in C++, for example, Linux system calls. Before the advent of modern C++, most people talked about "what is the difference between C and C++". Generally speaking, in addition to answering the object-oriented class features and the template features of generic programming, there is no other opinion or even a direct answer. "Almost" is also a lot of people. The Venn diagram in Figure 1.2 roughly answers the C and C++ related compatibility. + +![Figure 1.2: Compatabilities between ISO C and ISO C++](../../assets/figures/comparison.png) + +From now on, you should have the idea that "C++ is **not** a superset of C" in your mind (and not from the beginning, later [References for further reading](#further-readings) The difference between C++98 and C99 is given). When writing C++, you should also avoid using program styles such as `void*` whenever possible. When you have to use C, you should pay attention to the use of `extern "C"`, separate the C language code from the C++ code, and then unify the link, for instance: + +```cpp +// foo.h +#ifdef __cplusplus +extern "C" { +#endif + +int add(int x, int y); + +#ifdef __cplusplus +} +#endif + +// foo.c +int add(int x, int y) { + return x+y; +} + +// 1.1.cpp +#include "foo.h" +#include +#include + +int main() { + [out = std::ref(std::cout << "Result from C code: " << add(1, 2))](){ + out.get() << ".\n"; + }(); + return 0; +} +``` + +You should first compile the C code with `gcc`: + +```bash +gcc -c foo.c +``` + +Compile and output the `foo.o` file, and link the C++ code to the `.o` file using `clang++` (or both compile to `.o` and then link them together): + +```bash +clang++ 1.1.cpp foo.o -std=c++2a -o 1.1 +``` + +Of course, you can use `Makefile` to compile the above code: + +```makefile +C = gcc +CXX = clang++ + +SOURCE_C = foo.c +OBJECTS_C = foo.o + +SOURCE_CXX = 1.1.cpp + +TARGET = 1.1 +LDFLAGS_COMMON = -std=c++2a + +all: + $(C) -c $(SOURCE_C) + $(CXX) $(SOURCE_CXX) $(OBJECTS_C) $(LDFLAGS_COMMON) -o $(TARGET) + +clean: + rm -rf *.o $(TARGET) +``` + +> **Note**: Indentation in `Makefile` is a tab instead of a space character. If you copy this code directly into your editor, the tab may be automatically replaced. Please ensure the indentation in the `Makefile` is done by tabs. +> +> If you don't know the use of `Makefile`, it doesn't matter. In this tutorial, you won't build code that is written too complicated. You can also read this book by simply using `clang++ -std=c++2a` on the command line. + +If you are new to modern C++, you probably still don't understand the following small piece of code above, namely: + +```cpp +[out = std::ref(std::cout << "Result from C code: " << add(1, 2))](){ + out.get() << ".\n"; +}(); +``` + +Don't worry at the moment, we will come to meet them in our later chapters. + +[Table of Content](./toc.md) | [Previous Chapter](./00-preface.md) | [Next Chapter: Language Usability Enhancements](./02-usability.md) + +## Further Readings + +- [A Tour of C++ (2nd Edition) Bjarne Stroustrup](https://www.amazon.com/dp/0134997832/ref=cm_sw_em_r_mt_dp_U_GogjDbHE2H53B) + [History of C++](http://en.cppreference.com/w/cpp/language/history) +- [C++ compiler support](https://en.cppreference.com/w/cpp/compiler_support) +- [Incompatibilities Between ISO C and ISO C++](http://david.tribble.com/text/cdiffs.htm#C99-vs-CPP98) + +## Licenses + +Creative Commons License
This work was written by [Ou Changkun](https://changkun.de) and licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. The code of this repository is open sourced under the [MIT license](../../LICENSE). diff --git a/book/en-us/02-usability.md b/book/en-us/02-usability.md new file mode 100644 index 00000000..eb8a21aa --- /dev/null +++ b/book/en-us/02-usability.md @@ -0,0 +1,1120 @@ +--- +title: "Chapter 02: Language Usability Enhancements" +type: book-en-us +order: 2 +--- + +# Chapter 02: Language Usability Enhancements + +[TOC] + +When we declare, define a variable or constant, and control the flow of code, +object-oriented functions, template programming, etc., before the runtime, +it may happen when writing code or compiler compiling code. +To this end, we usually talk about **language usability**, +which refers to the language behavior that occurred before the runtime. + +## 2.1 Constants + +### nullptr + +The purpose of `nullptr` appears to replace `NULL`. There are **null pointer constants** in the C and C++ languages, +which can be implicitly converted to null pointer value of any pointer type, +or null member pointer value of any pointer-to-member type in C++. +`NULL` is provided by the standard library implementation and defined as an implementation-defined null pointer constant. +In C, some standard libraries defines `NULL` as `((void*)0)` and some define it as `0`. + +C++ **does not allow** to implicitly convert `void *` to other types, and thus `((void*)0)` is not a valid implementation +of `NULL`. If the standard library tries to define `NULL` as `((void*)0)`, then compilation error would occur in the following code: + +```cpp +char *ch = NULL; +``` + +C++ without the `void *` implicit conversion has to define `NULL` as `0`. +This still creates a new problem. Defining `NULL` to `0` will cause the overloading feature in `C++` to be confusing. +Consider the following two `foo` functions: + +```cpp +void foo(char*); +void foo(int); +``` + +Then the `foo(NULL);` statement will call `foo(int)`, which will cause the code to be counterintuitive. + +To solve this problem, C++11 introduced the `nullptr` keyword, which is specifically used to distinguish null pointers, `0`. The type of `nullptr` is `nullptr_t`, which can be implicitly converted to any pointer or member pointer type, and can be compared equally or unequally with them. + +You can try to compile the following code using clang++: + +```cpp +#include +#include + +void foo(char *); +void foo(int); + +int main() { + if (std::is_same::value) + std::cout << "NULL == 0" << std::endl; + if (std::is_same::value) + std::cout << "NULL == (void *)0" << std::endl; + if (std::is_same::value) + std::cout << "NULL == nullptr" << std::endl; + + foo(0); // will call foo(int) + // foo(NULL); // doesn't compile + foo(nullptr); // will call foo(char*) + return 0; +} + +void foo(char *) { + std::cout << "foo(char*) is called" << std::endl; +} +void foo(int i) { + std::cout << "foo(int) is called" << std::endl; +} +``` + +The outputs are: + +```bash +foo(int) is called +foo(char*) is called +``` + +From the output we can see that `NULL` is different from `0` and `nullptr`. +So, develop the habit of using `nullptr` directly. + +In addition, in the above code, we used `decltype` and +`std::is_same` which are modern C++ syntax. +In simple terms, `decltype` is used for type derivation, +and `std::is_same` is used to compare the equality of the two types. +We will discuss them in detail later in the [decltype](#decltype) section. + +### constexpr + +C++ itself already has the concept of constant expressions, such as 1+2, +3\*4. Such expressions always produce the same result without any side effects. +If the compiler can directly optimize and embed these expressions into the program at +compile-time, it will increase the performance of the program. A very obvious example +is in the definition phase of an array: + +```cpp +#include +#define LEN 10 + +int len_foo() { + int i = 2; + return i; +} +constexpr int len_foo_constexpr() { + return 5; +} + +constexpr int fibonacci(const int n) { + return n == 1 || n == 2 ? 1 : fibonacci(n-1) + fibonacci(n-2); +} + + +int main() { + char arr_1[10]; // legal + char arr_2[LEN]; // legal + + int len = 10; + // char arr_3[len]; // illegal + + const int len_2 = len + 1; + constexpr int len_2_constexpr = 1 + 2 + 3; + // char arr_4[len_2]; // illegal, but ok for most of the compilers + char arr_4[len_2_constexpr]; // legal + + // char arr_5[len_foo()+5]; // illegal + char arr_6[len_foo_constexpr() + 1]; // legal + + // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 + std::cout << fibonacci(10) << std::endl; + + return 0; +} +``` + +In the above example, `char arr_4[len_2]` may be confusing because `len_2` has been defined as a constant. +Why is `char arr_4[len_2]` still illegal? +This is because the length of the array in the C++ standard must be a constant expression, +and for `len_2`, this is a `const` constant, not a constant expression, +so even if this behavior is supported by most compilers, but it is an illegal behavior, +we need to use the `constexpr` feature introduced in C++11, which will be introduced next, +to solve this problem; for `arr_5`, before C++98 The compiler cannot know that `len_foo()` +actually returns a constant at runtime, which causes illegal production. + +> Note that most compilers now have their compiler optimizations. +> Many illegal behaviors become legal under the compiler's optimization. +> If you need to reproduce the error, you need to use the old version of the compiler. + +C++11 provides `constexpr` to let the user explicitly declare that the function or +object constructor will become a constant expression at compile time. +This keyword explicitly tells the compiler that it should verify that `len_foo` +should be a compile-time constant expression. + +In addition, the function of `constexpr` can use recursion: + +```cpp +constexpr int fibonacci(const int n) { + return n == 1 || n == 2 ? 1 : fibonacci(n-1) + fibonacci(n-2); +} +``` + +Starting with C++14, +the constexpr function can use simple statements such as local variables, +loops, and branches internally. +For example, the following code cannot be compiled under the C++11 standard: + +```cpp +constexpr int fibonacci(const int n) { + if(n == 1) return 1; + if(n == 2) return 1; + return fibonacci(n-1) + fibonacci(n-2); +} +``` + +To do this, we can write a simplified version like this +to make the function available from C++11: + +```cpp +constexpr int fibonacci(const int n) { + return n == 1 || n == 2 ? 1 : fibonacci(n-1) + fibonacci(n-2); +} +``` + +## 2.2 Variables and initialization + +### if-switch + +In traditional C++, the declaration of a variable can declare a temporary variable `int` +even though it can be located anywhere, even within a `for` statement, +but there is always no way to declare a temporary variable in the `if` and `switch` statements. +E.g: + +```cpp +#include +#include +#include + +int main() { + std::vector vec = {1, 2, 3, 4}; + + // since c++17, can be simplified by using `auto` + const std::vector::iterator itr = std::find(vec.begin(), vec.end(), 2); + if (itr != vec.end()) { + *itr = 3; + } + + if (const std::vector::iterator itr = std::find(vec.begin(), vec.end(), 3); + itr != vec.end()) { + *itr = 4; + } + + // should output: 1, 4, 3, 4. can be simplified using `auto` + for (std::vector::iterator element = vec.begin(); element != vec.end(); + ++element) + std::cout << *element << std::endl; +} +``` + +In the above code, we can see that the `itr` variable is defined in the scope of +the entire `main()`, which causes us to rename the other when a variable need to traverse +the entire `std::vector` again. C++17 eliminates this limitation so that +we can do this in if(or switch): + +```cpp +if (const std::vector::iterator itr = std::find(vec.begin(), vec.end(), 3); + itr != vec.end()) { + *itr = 4; +} +``` + +Is it similar to the Go? + +### Initializer list + +Initialization is a very important language feature, +the most common one is when the object is initialized. +In traditional C++, different objects have different initialization methods, +such as ordinary arrays, PODs (**P**lain **O**ld **D**ata, +i.e. classes without constructs, destructors, and virtual functions) +Or struct type can be initialized with `{}`, +which is what we call the initialization list. +For the initialization of the class object, +you need to use the copy construct, +or you need to use `()`. +These different methods are specific to each other and cannot be generic. +E.g: + +```cpp +#include +#include + +class Foo { +public: + int value_a; + int value_b; + Foo(int a, int b) : value_a(a), value_b(b) {} +}; + +int main() { + // before C++11 + int arr[3] = {1, 2, 3}; + Foo foo(1, 2); + std::vector vec = {1, 2, 3, 4, 5}; + + std::cout << "arr[0]: " << arr[0] << std::endl; + std::cout << "foo:" << foo.value_a << ", " << foo.value_b << std::endl; + for (std::vector::iterator it = vec.begin(); it != vec.end(); ++it) { + std::cout << *it << std::endl; + } + return 0; +} +``` + +To solve this problem, +C++11 first binds the concept of the initialization list to the type +and calls it `std::initializer_list`, +allowing the constructor or other function to use the initialization list +like a parameter, which is the initialization of class objects provides +a unified bridge between normal arrays and POD initialization methods, +such as: + +```cpp +#include +#include +#include + +class MagicFoo { +public: + std::vector vec; + MagicFoo(std::initializer_list list) { + for (std::initializer_list::iterator it = list.begin(); + it != list.end(); ++it) + vec.push_back(*it); + } +}; +int main() { + // after C++11 + MagicFoo magicFoo = {1, 2, 3, 4, 5}; + + std::cout << "magicFoo: "; + for (std::vector::iterator it = magicFoo.vec.begin(); + it != magicFoo.vec.end(); ++it) + std::cout << *it << std::endl; +} +``` + +This constructor is called the initialize list constructor, and the type with +this constructor will be specially taken care of during initialization. + +In addition to the object construction, the initialization list can also +be used as a formal parameter of a normal function, for example: + +```Cpp +public: + void foo(std::initializer_list list) { + for (std::initializer_list::iterator it = list.begin(); + it != list.end(); ++it) vec.push_back(*it); + } + +magicFoo.foo({6,7,8,9}); +``` + +Second, C++11 also provides a uniform syntax for initializing arbitrary objects, such as: + +```cpp +Foo foo2 {3, 4}; +``` + +### Structured binding + +Structured bindings provide functionality similar to the multiple return values +provided in other languages. In the chapter on containers, +we will learn that C++11 has added a `std::tuple` container for +constructing a tuple that encloses multiple return values. But the flaw +is that C++11/14 does not provide a simple way to get and define +the elements in the tuple from the tuple, +although we can unpack the tuple using `std::tie` +But we still have to be very clear about how many objects this tuple contains, +what type of each object is, very troublesome. + +C++17 completes this setting, +and the structured bindings let us write code like this: + +```cpp +#include +#include + +std::tuple f() { + return std::make_tuple(1, 2.3, "456"); +} + +int main() { + auto [x, y, z] = f(); + std::cout << x << ", " << y << ", " << z << std::endl; + return 0; +} +``` + +The `auto` type derivation is described in the +[auto type inference](#auto) section. + +## 2.3 Type inference + +In traditional C and C++, the types of parameters must be clearly defined, which does not help us to quickly encode, especially when we are faced with a large number of complex template types, we must indicate the type of variables to proceed. Subsequent coding, which not only slows down our development efficiency but also makes the code stinking and long. + +C++11 introduces the two keywords `auto` and `decltype` to implement type derivation, letting the compiler worry about the type of the variable. This makes C++ the same as other modern programming languages, in a way that provides the habit of not having to worry about variable types. + +### auto + +`auto` has been in C++ for a long time, but it always exists as an indicator of a storage type, coexisting with `register`. In traditional C++, if a variable is not declared as a `register` variable, it is automatically treated as an `auto` variable. And with `register` being deprecated (used as a reserved keyword in C++17 and later used, it doesn't currently make sense), the semantic change to `auto` is very natural. + +One of the most common and notable examples of type derivation using `auto` is the iterator. You should see the lengthy iterative writing in traditional C++ in the previous section: + +```cpp +// before C++11 +// cbegin() returns vector::const_iterator +// and therefore it is type vector::const_iterator +for(vector::const_iterator it = vec.cbegin(); it != vec.cend(); ++it) +``` + +When we have `auto`: + +```cpp +#include +#include +#include + +class MagicFoo { +public: + std::vector vec; + MagicFoo(std::initializer_list list) { + for (auto it = list.begin(); it != list.end(); ++it) { + vec.push_back(*it); + } + } +}; + +int main() { + MagicFoo magicFoo = {1, 2, 3, 4, 5}; + std::cout << "magicFoo: "; + for (auto it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) { + std::cout << *it << ", "; + } + std::cout << std::endl; + return 0; +} +``` + +Some other common usages: + +```cpp +auto i = 5; // i as int +auto arr = new auto(10); // arr as int * +``` + +Since C++ 14, `auto` can even be used as function arguments in generic lambda expressions, +and such functionality is generalized to normal functions in C++ 20. +Consider the following example: + +```cpp +auto add14 = [](auto x, auto y) -> int { + return x+y; +} + +int add20(auto x, auto y) { + return x+y; +} + +auto i = 5; // type int +auto j = 6; // type int +std::cout << add14(i, j) << std::endl; +std::cout << add20(i, j) << std::endl; +``` + +> **Note**: `auto` cannot be used to derive array types yet: +> +> ```cpp +> auto auto_arr2[10] = {arr}; // illegal, can't infer array type +> +> 2.6.auto.cpp:30:19: error: 'auto_arr2' declared as array of 'auto' +> auto auto_arr2[10] = {arr}; +> ``` + +### decltype + +The `decltype` keyword is used to solve the defect that the auto keyword +can only type the variable. Its usage is very similar to `typeof`: + +```cpp +decltype(expression) +``` + +Sometimes we may need to calculate the type of an expression, for example: + +```cpp +auto x = 1; +auto y = 2; +decltype(x+y) z; +``` + +You have seen in the previous example that +`decltype` is used to infer the usage of the type. +The following example is to determine +if the above variables `x, y, z` are of the same type: + +```cpp +if (std::is_same::value) + std::cout << "type x == int" << std::endl; +if (std::is_same::value) + std::cout << "type x == float" << std::endl; +if (std::is_same::value) + std::cout << "type z == type x" << std::endl; +``` + +Among them, `std::is_same` is used to determine whether +the two types `T` and `U` are equal. The output is: + +``` +type x == int +type z == type x +``` + +### tail type inference + +You may think that whether `auto` can be used to deduce the return type of a function. Still consider an example of an add function, which we have to write in traditional C++: + +```cpp +template +R add(T x, U y) { + return x+y; +} +``` + +> Note: There is no difference between typename and class in the template parameter list. Before the keyword typename appears, class is used to define the template parameters. However, when defining a variable with [nested dependency type](https://en.cppreference.com/w/cpp/language/dependent_name#The_typename_disambiguator_for_dependent_names) in the template, you need to use typename to eliminate ambiguity. + +Such code is very ugly because the programmer must explicitly +indicate the return type when using this template function. +But in fact, we don't know what kind of operation +the `add()` function will do, and what kind of return type to get. + +This problem was solved in C++11. Although you may immediately +react to using `decltype` to derive the type of `x+y`, +write something like this: + +```cpp +decltype(x+y) add(T x, U y) +``` + +But in fact, this way of writing can not be compiled. +This is because `x` and `y` have not been defined +when the compiler reads decltype(x+y). +To solve this problem, C++11 also introduces a trailing return type, +which uses the auto keyword to post the return type: + +```cpp +template +auto add2(T x, U y) -> decltype(x+y){ + return x + y; +} +``` + +The good news is that from C++14 it is possible to directly derive the return value of +a normal function, so the following way becomes legal: + +```cpp +template +auto add3(T x, U y){ + return x + y; +} +``` + +You can check if the type derivation is correct: + +```cpp +// after c++11 +auto w = add2(1, 2.0); +if (std::is_same::value) { + std::cout << "w is double: "; +} +std::cout << w << std::endl; + +// after c++14 +auto q = add3(1.0, 2); +std::cout << "q: " << q << std::endl; +``` + +### decltype(auto) + +`decltype(auto)` is a slightly more complicated use of C++14. + +> To understand it you need to know the concept of parameter forwarding +> in C++, which we will cover in detail in the +> [Language Runtime Enhancements](./03-runtime.md) chapter, +> and you can come back to the contents of this section later. + +In simple terms, `decltype(auto)` is mainly used to derive +the return type of a forwarding function or package, +which does not require us to explicitly specify +the parameter expression of `decltype`. +Consider the following example, when we need to wrap the following +two functions: + +```cpp +std::string lookup1(); +std::string& lookup2(); +``` + +In C++11: + +```cpp +std::string look_up_a_string_1() { + return lookup1(); +} +std::string& look_up_a_string_2() { + return lookup2(); +} +``` + +With `decltype(auto)`, we can let the compiler do this annoying parameter forwarding: + +```cpp +decltype(auto) look_up_a_string_1() { + return lookup1(); +} +decltype(auto) look_up_a_string_2() { + return lookup2(); +} +``` + +## 2.4 Control flow + +### if constexpr + +As we saw at the beginning of this chapter, we know that C++11 introduces the `constexpr` keyword, which compiles expressions or functions into constant results. A natural idea is that if we introduce this feature into the conditional judgment, let the code complete the branch judgment at compile-time, can it make the program more efficient? C++17 introduces the `constexpr` keyword into the `if` statement, allowing you to declare the condition of a constant expression in your code. Consider the following code: + +```cpp +#include + +template +auto print_type_info(const T& t) { + if constexpr (std::is_integral::value) { + return t + 1; + } else { + return t + 0.001; + } +} +int main() { + std::cout << print_type_info(5) << std::endl; + std::cout << print_type_info(3.14) << std::endl; +} +``` + +At compile time, the actual code will behave as follows: + +```cpp +int print_type_info(const int& t) { + return t + 1; +} +double print_type_info(const double& t) { + return t + 0.001; +} +int main() { + std::cout << print_type_info(5) << std::endl; + std::cout << print_type_info(3.14) << std::endl; +} +``` + +### Range-based for loop + +Finally, C++11 introduces a range-based iterative method, and we can write loops that are as concise +as Python, and we can further simplify the previous example: + +```cpp +#include +#include +#include + +int main() { + std::vector vec = {1, 2, 3, 4}; + if (auto itr = std::find(vec.begin(), vec.end(), 3); itr != vec.end()) *itr = 4; + for (auto element : vec) + std::cout << element << std::endl; // read only + for (auto &element : vec) { + element += 1; // writeable + } + for (auto element : vec) + std::cout << element << std::endl; // read only +} +``` + +## 2.5 Templates + +C++ templates have always been a special art of the language, and templates can even be used independently as a new language. The philosophy of the template is to throw all the problems that can be processed at compile time into the compile time, and only deal with those core dynamic services at runtime, to greatly optimize the performance of the runtime. Therefore, templates are also regarded by many as one of the black magic of C++. + +### Extern templates + +In traditional C++, templates are instantiated by the compiler only when they are used. In other words, as long as a fully defined template is encountered in the code compiled in each compilation unit (file), it will be instantiated. This results in an increase in compile time due to repeated instantiations. Also, we have no way to tell the compiler not to trigger the instantiation of the template. + +To this end, C++11 introduces an external template that extends the syntax of the original mandatory compiler to instantiate a template at a specific location, allowing us to explicitly tell the compiler when to instantiate the template: + +```cpp +template class std::vector; // force instantiation +extern template class std::vector; // should not instantiation in current file +``` + +### The ">" + +In the traditional C++ compiler, `>>` is always treated as a right shift operator. But actually we can easily write the code for the nested template: + +```cpp +std::vector> matrix; +``` + +This is not compiled under the traditional C++ compiler, +and C++11 starts with continuous right angle brackets that become legal +and can be compiled successfully. +Even the following writing can be compiled by: + +```cpp +template +class MagicType { + bool magic = T; +}; + +// in main function: +std::vector2)>> magic; // legal, but not recommended +``` + +### Type alias templates + +Before you understand the type alias template, you need to understand the difference between "template" and "type". Carefully understand this sentence: **Templates are used to generate types.** In traditional C++, `typedef` can define a new name for the type, but there is no way to define a new name for the template. Because the template is not a type. E.g: + +```cpp +template +class MagicType { +public: + T dark; + U magic; +}; + +// not allowed +template +typedef MagicType, std::string> FakeDarkMagic; +``` + +C++11 uses `using` to introduce the following form of writing, and at the same time supports the same effect as the traditional `typedef`: + +> Usually, we use `typedef` to define the alias syntax: `typedef original name new name; `, but the definition syntax for aliases such as function pointers is different, which usually causes a certain degree of difficulty for direct reading. + +```cpp +typedef int (*process)(void *); +using NewProcess = int(*)(void *); +template +using TrueDarkMagic = MagicType, std::string>; + +int main() { + TrueDarkMagic you; +} +``` + +### Variadic templates + +The template has always been one of C++'s unique **Black Magic**. +In traditional C++, +both a class template and a function template could only accept +a fixed set of template parameters as specified; +C++11 added a new representation, allowing any number, +template parameters of any category, +and there is no need to fix the number of parameters when defining. + +```cpp +template class Magic; +``` + +The template class Magic object can accept an unrestricted number of typename as +a formal parameter of the template, such as the following definition: + +```cpp +class Magic, + std::map>> darkMagic; +``` + +Since it is arbitrary, a template parameter with a number of 0 is also possible: `class Magic nothing;`. + +If you do not want to generate 0 template parameters, you can manually define at least one template parameter: + +```cpp +template class Magic; +``` + +The variable length parameter template can also be directly adjusted to the template function. +The `printf` function in the traditional C, although it can also reach the call of an indefinite number of formal parameters, is not class safe. In addition to the variable-length parameter functions that define class safety, C++11 can also make printf-like functions naturally handle objects that are not self-contained. In addition to the use of `...` in the template parameters to indicate the indefinite length of the template parameters, the function parameters also use the same representation to represent the indefinite length parameters, which provides a convenient means for us to simply write variable length parameter functions, such as: + +```cpp +template void printf(const std::string &str, Args... args); +``` + +Then we define variable length template parameters, +how to unpack the parameters? + +First, we can use `sizeof...` to calculate the number of arguments: + +```cpp +#include +template +void magic(Ts... args) { + std::cout << sizeof...(args) << std::endl; +} +``` + +We can pass any number of arguments to the `magic` function: + +```cpp +magic(); // 0 +magic(1); // 1 +magic(1, ""); // 2 +``` + +Second, the parameters are unpacked. So far there is no simple way to process +the parameter package, but there are two classic processing methods: + +**1. Recursive template function** + +Recursion is a very easy way to think of and the most classic approach. This method continually recursively passes template parameters to the function, thereby achieving the purpose of recursively traversing all template parameters: + +```cpp +#include +template +void printf1(T0 value) { + std::cout << value << std::endl; +} +template +void printf1(T value, Ts... args) { + std::cout << value << std::endl; + printf1(args...); +} +int main() { + printf1(1, 2, "123", 1.1); + return 0; +} +``` + +**2. Variable parameter template expansion** + +You should feel that this is very cumbersome. Added support for variable parameter template expansion in C++17, so you can write `printf` in a function: + +```cpp +template +void printf2(T0 t0, T... t) { + std::cout << t0 << std::endl; + if constexpr (sizeof...(t)> 0) printf2(t...); +} +``` + +> In fact, sometimes we use variable parameter templates, but we don't necessarily need to traverse the parameters one by one. We can use the features of `std::bind` and perfect forwarding to achieve the binding of functions and parameters, thus achieving success. The purpose of the call. + +**3. Initialize list expansion** + +Recursive template functions are standard practice, but the obvious drawback is that you must define a function that terminates recursion. + +Here is a description of the black magic that is expanded using the initialization list: + +```cpp +template +auto printf3(T value, Ts... args) { + std::cout << value << std::endl; + (void) std::initializer_list{([&args] { + std::cout << args << std::endl; + }(), value)...}; +} +``` + +In this code, the initialization list provided in C++11 and the properties of the Lambda expression (mentioned in the next section) are additionally used. + +By initializing the list, `(lambda expression, value)...` will be expanded. Due to the appearance of the comma expression, the previous lambda expression is executed first, and the output of the parameter is completed. +To avoid compiler warnings, we can explicitly convert `std::initializer_list` to `void`. + +### Fold expression + +In C++ 17, this feature of the variable length parameter is further brought to the expression, consider the following example: + +```cpp +#include +template +auto sum(T ... t) { + return (t + ...); +} +int main() { + std::cout << sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl; +} +``` + +### Non-type template parameter deduction + +What we mainly mentioned above is a form of template parameters: type template parameters. + +```cpp +template +auto add(T t, U u) { + return t+u; +} +``` + +The parameters of the template `T` and `U` are specific types. +But there is also a common form of template parameter that allows different literals +to be template parameters, i.e. non-type template parameters: + +```cpp +template +class buffer_t { +public: + T& alloc(); + void free(T& item); +private: + T data[BufSize]; +} + +buffer_t buf; // 100 as template parameter +``` + +In this form of template parameters, we can pass `100` as a parameter to the template. +After C++11 introduced the feature of type derivation, we will naturally ask, since the template parameters here. +Passing with a specific literal, can the compiler assist us in type derivation, +By using the placeholder `auto`, there is no longer a need to explicitly specify the type? +Fortunately, C++17 introduces this feature, and we can indeed use the `auto` keyword to let the compiler assist in the completion of specific types of derivation. +E.g: + +```cpp +template void foo() { + std::cout << value << std::endl; + return; +} + +int main() { + foo<10>(); // value as int +} +``` + +## 2.6 Object-oriented + +### Delegate constructor + +C++11 introduces the concept of a delegate construct, which allows a constructor to call another constructor +in a constructor in the same class, thus simplifying the code: + +```cpp +#include +class Base { +public: + int value1; + int value2; + Base() { + value1 = 1; + } + Base(int value) : Base() { // delegate Base() constructor + value2 = value; + } +}; + +int main() { + Base b(2); + std::cout << b.value1 << std::endl; + std::cout << b.value2 << std::endl; +} +``` + +### Inheritance constructor + +In traditional C++, constructors need to pass arguments one by one if they need inheritance, which leads to inefficiency. C++11 introduces the concept of inheritance constructors using the keyword using: + +```cpp +#include +class Base { +public: + int value1; + int value2; + Base() { + value1 = 1; + } + Base(int value) : Base() { // delegate Base() constructor + value2 = value; + } +}; +class Subclass : public Base { +public: + using Base::Base; // inheritance constructor +}; +int main() { + Subclass s(3); + std::cout << s.value1 << std::endl; + std::cout << s.value2 << std::endl; +} +``` + +### Explicit virtual function overwrite + +In traditional C++, it is often prone to accidentally overloading virtual functions. E.g: + +```cpp +struct Base { + virtual void foo(); +}; +struct SubClass: Base { + void foo(); +}; +``` + +`SubClass::foo` may not be a programmer trying to overload a virtual function, just adding a function with the same name. Another possible scenario is that when the virtual function of the base class is deleted, the subclass owns the old function and no longer overloads the virtual function and turns it into a normal class method, which has catastrophic consequences. + +C++11 introduces the two keywords `override` and `final` to prevent this from happening. + +### override + +When overriding a virtual function, introducing the `override` keyword will explicitly tell the compiler to overload, and the compiler will check if the base function has such a virtual function with consistent function signature, otherwise it will not compile: + +```cpp +struct Base { + virtual void foo(int); +}; +struct SubClass: Base { + virtual void foo(int) override; // legal + virtual void foo(float) override; // illegal, no virtual function in super class +}; +``` + +### final + +`final` is to prevent the class from being continued to inherit and to terminate +the virtual function to continue to be overloaded. + +```cpp +struct Base { + virtual void foo() final; +}; +struct SubClass1 final: Base { +}; // legal + +struct SubClass2 : SubClass1 { +}; // illegal, SubClass1 has final + +struct SubClass3: Base { + void foo(); // illegal, foo has final +}; +``` + +### Explicit delete default function + +In traditional C++, if the programmer does not provide it, the compiler will default to generating default constructors, copy constructs, assignment operators, and destructors for the object. Besides, C++ also defines operators such as `new` `delete` for all classes. This part of the function can be overridden when the programmer needs it. + +This raises some requirements: the ability to accurately control the generation of default functions cannot be controlled. For example, when copying a class is prohibited, the copy constructor and the assignment operator must be declared as `private`. Trying to use these undefined functions will result in compilation or link errors, which is a very unconventional way. + +Also, the default constructor generated by the compiler cannot exist at the same time as the user-defined constructor. If the user defines any constructor, the compiler will no longer generate the default constructor, but sometimes we want to have both constructors at the same time, which is awkward. + +C++11 provides a solution to the above requirements, allowing explicit declarations to take or reject functions that come with the compiler. E.g: + +```cpp +class Magic { + public: + Magic() = default; // explicit let compiler use default constructor + Magic& operator=(const Magic&) = delete; // explicit declare refuse constructor + Magic(int magic_number); +} +``` + +### Strongly typed enumerations + +In traditional C++, enumerated types are not type-safe, and enumerated types are treated as integers, which allows two completely different enumerated types to be directly compared (although the compiler gives the check, but not all), ** Even the enumeration value names of different enum types in the same namespace cannot be the same**, which is usually not what we want to see. + +C++11 introduces an enumeration class and declares it using the syntax of `enum class`: + +```cpp +enum class new_enum : unsigned int { + value1, + value2, + value3 = 100, + value4 = 100 +}; +``` + +The enumeration thus defined implements type safety. First, it cannot be implicitly converted to an integer, nor can it be compared to integer numbers, and it is even less likely to compare enumerated values of different enumerated types. But if the values specified are the same between the same enumerated values, then you can compare: + +```cpp +if (new_enum::value3 == new_enum::value4) { // true + std::cout << "new_enum::value3 == new_enum::value4" << std::endl; +} +``` + +In this syntax, the enumeration type is followed by a colon and a type keyword to specify the type of the enumeration value in the enumeration, which allows us to assign a value to the enumeration (int is used by default when not specified). + +And we want to get the value of the enumeration value, we will have to explicitly type conversion, but we can overload the `<<` operator to output, you can collect the following code snippet: + +```cpp +#include +template +std::ostream& operator<<( + typename std::enable_if::value, + std::ostream>::type& stream, const T& e) +{ + return stream << static_cast::type>(e); +} +``` + +At this point, the following code will be able to be compiled: + +```cpp +std::cout << new_enum::value3 << std::endl +``` + +## Conclusion + +This section introduces the enhancements to language usability in modern C++, which I believe are the most important features that almost everyone needs to know and use: + +1. Auto type derivation +2. Scope for iteration +3. Initialization list +4. Variable parameter template + +## Exercises + +1. Using structured binding, implement the following functions with just one line of function code: + + ```cpp + #include + #include