├── .dir-locals.el ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── COPYING ├── README.md ├── asset-sources └── header-icon.svg ├── assets ├── by-sa.pdf └── header-icon.pdf ├── bibliography.bib ├── cmake └── modules │ └── UseLATEX.cmake ├── counting-in-c++.tex ├── examples ├── constexpr │ ├── constexpr-11.cpp │ ├── constexpr-14.cpp │ └── constexpr-98.cpp ├── extern-template │ ├── bar-11.cpp │ ├── bar-98.cpp │ ├── factorial-11.cpp │ ├── factorial-11.hpp │ ├── factorial-98.hpp │ ├── foo-11.cpp │ ├── foo-98.cpp │ └── main.cpp ├── nullptr │ ├── nullptr-11.cpp │ └── nullptr-98.cpp ├── reference-wrapper │ └── capacity_tracker.cpp ├── static-assert │ ├── even_sized_array-11.cpp │ └── even_sized_array-98.cpp ├── thread │ └── flood.cpp ├── tuple │ └── binding.cpp ├── type-traits │ ├── main-11.cpp │ ├── main-98.cpp │ ├── mix-11.hpp │ └── mix-98.hpp ├── uniform-initialization │ └── struct.cpp ├── variable-template │ ├── main-11.cpp │ └── main-14.cpp └── variadic-template │ ├── callbacks.cpp │ ├── collect_type_names.cpp │ ├── dispatcher-11.hpp │ ├── dispatcher-98.hpp │ ├── dispatcher_impl.hpp │ ├── dispatcher_impl_0.hpp │ ├── dispatcher_impl_1.hpp │ ├── dispatcher_impl_2.hpp │ ├── main-11.cpp │ └── main-98.cpp ├── html-cleanup ├── CMakeLists.txt └── main.cpp ├── html-preclean.sh ├── make4ht.cfg ├── parts ├── 11 │ ├── array.tex │ ├── auto.tex │ ├── bind.tex │ ├── constexpr.tex │ ├── decltype.tex │ ├── defaulted-constructors.tex │ ├── delegated-constructors.tex │ ├── deleted-constructors.tex │ ├── extern-template.tex │ ├── free-begin.tex │ ├── function.tex │ ├── hash-table.tex │ ├── initializer-list.tex │ ├── lambdas.tex │ ├── miscellaneous.tex │ ├── move.tex │ ├── nullptr.tex │ ├── override-and-final.tex │ ├── prev-next.tex │ ├── random.tex │ ├── range-based-for-loops.tex │ ├── reference-wrapper.tex │ ├── rvalue-reference.tex │ ├── scoped-enumerations.tex │ ├── smart-pointers.tex │ ├── static-assert.tex │ ├── template-aliases.tex │ ├── thread.tex │ ├── tuple.tex │ ├── type-traits.tex │ ├── uniform-initialization.tex │ ├── using-parent-function.tex │ └── variadic-template.tex ├── 14 │ ├── binary-literals.tex │ ├── decltype-auto.tex │ ├── deprecated.tex │ ├── exchange.tex │ ├── generic-lambdas.tex │ ├── integer-sequence.tex │ ├── lambda-capture.tex │ ├── make-unique.tex │ ├── number-separator.tex │ ├── relaxed-constexpr.tex │ ├── return-type-deduction.tex │ ├── tuple-addressing-by-type.tex │ └── variable-templates.tex ├── 11.tex ├── 14.tex ├── cpp-general.tex ├── license.tex ├── preface.tex └── title-page.tex ├── style.css └── style └── code-listings.tex /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ( 2 | (latex-mode 3 | . ((eval . (turn-on-auto-fill)) 4 | (ispell-local-dictionary . "english") 5 | (mode . flyspell) 6 | ) 7 | ) 8 | ) 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | dist: focal 4 | 5 | branches: 6 | except: 7 | - continuous 8 | 9 | before_install: 10 | - sudo apt-get install --assume-yes 11 | cmake 12 | texlive-fonts-extra 13 | texlive-fonts-extra-links 14 | texlive-fonts-recommended 15 | texlive-latex-base 16 | texlive-latex-extra 17 | texlive-latex-recommended 18 | texlive-plain-generic 19 | 20 | before_script: 21 | - export SHORT_COMMIT=$(git rev-parse --short HEAD) 22 | 23 | script: 24 | - mkdir build 25 | - cd build 26 | - cmake .. 27 | - make 28 | - mv counting-in-c++.pdf counting-in-c++-wip.pdf 29 | 30 | before_deploy: 31 | - if [ "$TRAVIS_BRANCH" != "master" ]; then exit; fi 32 | - git config --local user.name "Travis CI" 33 | - git config --local user.email "builds@example.com" 34 | - git remote add origin-oauth 35 | $(git config remote.origin.url | sed "s/\(https:\/\/\)/\1$GITHUB_TOKEN@/") 36 | - git tag --force continuous 37 | - git push origin-oauth --tags --force 38 | 39 | deploy: 40 | provider: releases 41 | token: $GITHUB_TOKEN 42 | edge: true 43 | file: counting-in-c++-wip.pdf 44 | overwrite: true 45 | release_notes: 46 | - This version is created automatically from the latest commit on master. 47 | on: 48 | branch: master 49 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project( 4 | counting-in-c++ 5 | LANGUAGES CXX 6 | VERSION 1 7 | ) 8 | 9 | set( 10 | CMAKE_MODULE_PATH 11 | ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/modules/" 12 | ) 13 | 14 | add_subdirectory(html-cleanup) 15 | 16 | include(UseLATEX) 17 | find_package(Threads) 18 | 19 | set(latex_example_files) 20 | 21 | function(add_example) 22 | cmake_parse_arguments( 23 | example 24 | "" 25 | "ROOT;STANDARD;TARGET" 26 | "FILES;LINKS" 27 | ${ARGN} 28 | ) 29 | 30 | set(source_root "examples/${example_ROOT}") 31 | set(examples) 32 | 33 | foreach(file ${example_FILES}) 34 | set(file_path "${source_root}/${file}") 35 | set(examples ${examples} "${file_path}") 36 | set(files ${files} ${file_path}) 37 | endforeach() 38 | 39 | set(latex_example_files ${latex_example_files} ${examples} PARENT_SCOPE) 40 | 41 | if(example_TARGET) 42 | set(target_name "${example_TARGET}") 43 | else() 44 | set(target_name ${example_ROOT}-${example_STANDARD}) 45 | endif() 46 | 47 | add_executable(${target_name} ${files}) 48 | set_property(TARGET ${target_name} PROPERTY CXX_STANDARD ${example_STANDARD}) 49 | target_include_directories(${target_name} PRIVATE ${source_root}) 50 | 51 | if(example_LINKS) 52 | target_link_libraries(${target_name} PRIVATE ${example_LINKS}) 53 | endif() 54 | endfunction() 55 | 56 | add_example( 57 | ROOT constexpr 58 | FILES constexpr-98.cpp 59 | STANDARD 98 60 | ) 61 | add_example( 62 | ROOT constexpr 63 | FILES constexpr-11.cpp 64 | STANDARD 11 65 | ) 66 | add_example( 67 | ROOT constexpr 68 | FILES constexpr-14.cpp 69 | STANDARD 14 70 | ) 71 | add_example( 72 | ROOT extern-template 73 | FILES main.cpp bar-98.cpp foo-98.cpp 74 | STANDARD 98 75 | ) 76 | add_example( 77 | ROOT extern-template 78 | FILES main.cpp bar-11.cpp foo-11.cpp factorial-11.cpp 79 | STANDARD 11 80 | ) 81 | add_example( 82 | ROOT nullptr 83 | FILES nullptr-11.cpp 84 | STANDARD 11 85 | ) 86 | add_example( 87 | ROOT reference-wrapper 88 | FILES capacity_tracker.cpp 89 | STANDARD 11 90 | ) 91 | add_example( 92 | ROOT thread 93 | FILES flood.cpp 94 | STANDARD 11 95 | LINKS Threads::Threads 96 | ) 97 | add_example( 98 | ROOT tuple 99 | FILES binding.cpp 100 | STANDARD 11 101 | ) 102 | add_example( 103 | ROOT type-traits 104 | FILES main-11.cpp 105 | STANDARD 11 106 | ) 107 | add_example( 108 | ROOT type-traits 109 | FILES main-98.cpp 110 | STANDARD 98 111 | ) 112 | add_example( 113 | ROOT uniform-initialization 114 | FILES struct.cpp 115 | STANDARD 11 116 | ) 117 | add_example( 118 | ROOT variadic-template 119 | FILES main-11.cpp callbacks.cpp 120 | STANDARD 11 121 | ) 122 | add_example( 123 | ROOT variadic-template 124 | FILES main-98.cpp callbacks.cpp 125 | STANDARD 98 126 | ) 127 | add_example( 128 | TARGET variadic-template-array 129 | ROOT variadic-template 130 | FILES collect_type_names.cpp 131 | STANDARD 11 132 | ) 133 | add_example( 134 | TARGET variable-template-11 135 | ROOT variable-template 136 | FILES main-11.cpp 137 | STANDARD 11 138 | ) 139 | add_example( 140 | TARGET variable-template-14 141 | ROOT variable-template 142 | FILES main-14.cpp 143 | STANDARD 14 144 | ) 145 | 146 | add_latex_document( 147 | counting-in-c++.tex 148 | 149 | BIBFILES 150 | bibliography.bib 151 | 152 | CONFIGURE 153 | counting-in-c++.tex 154 | 155 | IMAGE_DIRS 156 | assets 157 | 158 | INPUTS 159 | ${latex_example_files} 160 | 161 | examples/extern-template/factorial-11.hpp 162 | examples/extern-template/factorial-98.hpp 163 | examples/nullptr/nullptr-98.cpp 164 | examples/static-assert/even_sized_array-11.cpp 165 | examples/static-assert/even_sized_array-98.cpp 166 | examples/type-traits/mix-11.hpp 167 | examples/type-traits/mix-98.hpp 168 | examples/variadic-template/dispatcher-11.hpp 169 | examples/variadic-template/dispatcher-98.hpp 170 | examples/variadic-template/dispatcher_impl_1.hpp 171 | examples/variadic-template/dispatcher_impl_2.hpp 172 | 173 | parts/11.tex 174 | parts/14.tex 175 | parts/cpp-general.tex 176 | parts/license.tex 177 | parts/preface.tex 178 | parts/title-page.tex 179 | 180 | parts/11/array.tex 181 | parts/11/auto.tex 182 | parts/11/bind.tex 183 | parts/11/constexpr.tex 184 | parts/11/decltype.tex 185 | parts/11/defaulted-constructors.tex 186 | parts/11/delegated-constructors.tex 187 | parts/11/deleted-constructors.tex 188 | parts/11/extern-template.tex 189 | parts/11/free-begin.tex 190 | parts/11/function.tex 191 | parts/11/hash-table.tex 192 | parts/11/initializer-list.tex 193 | parts/11/lambdas.tex 194 | parts/11/miscellaneous.tex 195 | parts/11/move.tex 196 | parts/11/nullptr.tex 197 | parts/11/override-and-final.tex 198 | parts/11/prev-next.tex 199 | parts/11/random.tex 200 | parts/11/range-based-for-loops.tex 201 | parts/11/reference-wrapper.tex 202 | parts/11/rvalue-reference.tex 203 | parts/11/template-aliases.tex 204 | parts/11/scoped-enumerations.tex 205 | parts/11/smart-pointers.tex 206 | parts/11/static-assert.tex 207 | parts/11/thread.tex 208 | parts/11/tuple.tex 209 | parts/11/type-traits.tex 210 | parts/11/uniform-initialization.tex 211 | parts/11/using-parent-function.tex 212 | parts/11/variadic-template.tex 213 | 214 | parts/14/binary-literals.tex 215 | parts/14/decltype-auto.tex 216 | parts/14/deprecated.tex 217 | parts/14/exchange.tex 218 | parts/14/generic-lambdas.tex 219 | parts/14/integer-sequence.tex 220 | parts/14/lambda-capture.tex 221 | parts/14/make-unique.tex 222 | parts/14/number-separator.tex 223 | parts/14/relaxed-constexpr.tex 224 | parts/14/return-type-deduction.tex 225 | parts/14/tuple-addressing-by-type.tex 226 | parts/14/variable-templates.tex 227 | 228 | style/code-listings.tex 229 | ) 230 | 231 | find_program(tidy NAMES tidy REQUIRED) 232 | 233 | add_custom_target(latex2html 234 | COMMAND make4ht 235 | --format html5 236 | --config ${CMAKE_CURRENT_LIST_DIR}/make4ht.cfg 237 | --output-dir counting-in-cpp 238 | counting-in-c++.tex 239 | fn-in,4 240 | 241 | DEPENDS counting-in-c++.pdf 242 | ) 243 | 244 | add_custom_target(html-preclean 245 | COMMAND echo Preclean 246 | COMMAND "${CMAKE_CURRENT_LIST_DIR}/html-preclean.sh" 247 | DEPENDS latex2html 248 | ) 249 | 250 | add_custom_target(html-book 251 | COMMAND echo Customization 252 | COMMAND "${html_cleanup}" counting-in-cpp/*.html 253 | COMMAND cp "${CMAKE_CURRENT_LIST_DIR}/style.css" counting-in-cpp/ 254 | 255 | DEPENDS 256 | html-preclean 257 | html-cleanup 258 | "${CMAKE_CURRENT_LIST_DIR}/style.css" 259 | ) 260 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Counting from 98 to 14 in C++ 2 | 3 | This book is a (quite opinionated) overview of many features added in 4 | the C++ language and the standard library since the huge major update 5 | called C++11. 6 | 7 | [Get the PDF here.](https://github.com/j-jorge/counting-in-cpp/releases/tag/continuous), or [read it online](https://julien.jorge.st/counting-in-cpp/). 8 | 9 | My hope is that the reader will find here an intermediate view on the 10 | language, between the cold factual description from the standard and 11 | the various low level subtleties one can find on various forums and 12 | blogs. So, if by reading this book you learn something about the 13 | language or if you suddenly understand why some feature has been added 14 | at some point, I will have completed my mission. Additionally, I will 15 | sometimes complete a section with personnal or critical comments based 16 | on my own experience. 17 | 18 | The sections are quite short and suppose some basic knowledge of the 19 | language (pre-11 knowledge is enough). The casual C++ programmer will 20 | appreciate skimming through its content to get an overview the 21 | available tools. 22 | 23 | Please note that only C++11 is covered in the current state of this 24 | document. 25 | 26 | # Contributing 27 | 28 | Writing is hard, and at some point sentences and words become a fog of 29 | blurry shapes where I can't even see my own words. Sometimes also, the 30 | mood is not there and the tone becomes harsh. If you find any typo or 31 | badly formulated sentences, feel free to open a pull request. 32 | 33 | Large contributions are a delicate topic. Since the book is full of my 34 | personal opinion, and since my name is on the cover, I probably cannot 35 | accept biased contributions unless I fully agree with their author. If 36 | you want to address a topic, please do it in a neutral way. 37 | 38 | Finally, if you want to add a section about a not yet discussed 39 | feature, please do it. The idea is to present the features in a kind 40 | of tangible way, preferably based on the experience of someone 41 | actually using it in production code. 42 | 43 | # License 44 | 45 | The book is available under the terms of the Creative Commons 46 | Attribution-Share Alike 4.0 International License. 47 | 48 | Note that I don't require the transfer of copyright ownership on the 49 | contributions, so a good way to keep this book forever free is simply 50 | to contribute! (_wink_). 51 | 52 | -------------------------------------------------------------------------------- /assets/by-sa.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-jorge/counting-in-cpp/bed6ae7c1781c5455041c1c5eda7698edf59d007/assets/by-sa.pdf -------------------------------------------------------------------------------- /assets/header-icon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/j-jorge/counting-in-cpp/bed6ae7c1781c5455041c1c5eda7698edf59d007/assets/header-icon.pdf -------------------------------------------------------------------------------- /bibliography.bib: -------------------------------------------------------------------------------- 1 | @book{clean-code, 2 | author = {Martin, Robert C.}, 3 | title = {Clean Code: A Handbook of Agile Software Craftsmanship}, 4 | year = {2008}, 5 | isbn = {0132350882}, 6 | publisher = {Prentice Hall PTR}, 7 | address = {USA}, 8 | edition = {1}, 9 | abstract = {Even bad code can function. But if code isnt clean, it 10 | can bring a development organization to its 11 | knees. Every year, countless hours and significant 12 | resources are lost because of poorly written 13 | code. But it doesnt have to be that way.Noted 14 | software expert Robert C. Martin, presents a 15 | revolutionary paradigm with Clean Code: A Handbook 16 | of Agile Software Craftsmanship. Martin, who has 17 | helped bring agile principles from a practitioners 18 | point of view to tens of thousands of programmers, 19 | has teamed up with his colleagues from Object Mentor 20 | to distill their best agile practice of cleaning 21 | code on the fly into a book that will instill within 22 | you the values of software craftsman, and make you a 23 | better programmerbut only if you work at it.What 24 | kind of work will you be doing? Youll be reading 25 | codelots of code. And you will be challenged to 26 | think about whats right about that code, and whats 27 | wrong with it. More importantly you will be 28 | challenged to reassess your professional values and 29 | your commitment to your craft. Clean Code is divided 30 | into three parts. The first describes the 31 | principles, patterns, and practices of writing clean 32 | code. The second part consists of several case 33 | studies of increasing complexity. Each case study is 34 | an exercise in cleaning up codeof transforming a 35 | code base that has some problems into one that is 36 | sound and efficient. The third part is the payoff: a 37 | single chapter containing a list of heuristics and 38 | smells gathered while creating the case studies. The 39 | result is a knowledge base that describes the way we 40 | think when we write, read, and clean code.Readers 41 | will come away from this book understandingHow to 42 | tell the difference between good and bad codeHow to 43 | write good code and how to transform bad code into 44 | good codeHow to create good names, good functions, 45 | good objects, and good classesHow to format code for 46 | maximum readability How to implement complete error 47 | handling without obscuring code logicHow to unit 48 | test and practice test-driven developmentWhat smells 49 | and heuristics can help you identify bad codeThis 50 | book is a must for any developer, software engineer, 51 | project manager, team lead, or systems analyst with 52 | an interest in producing better code.} 53 | } 54 | 55 | @book{code-complete, 56 | author = {McConnell, Steve}, 57 | title = {Code Complete, Second Edition}, 58 | year = {2004}, 59 | isbn = {0735619670}, 60 | publisher = {Microsoft Press}, 61 | address = {USA}, 62 | abstract = {Take a strategic approach to software construction-and 63 | produce superior products-with this fully updated 64 | edition of Steve McConnell's critically praised and 65 | award-winning guide to software development best 66 | practices.} 67 | } 68 | 69 | @book{the-cpp-programming-language-1st, 70 | author = {Stroustrup, Bjarne}, 71 | title = {The C++ Programming Language}, 72 | publisher = {Addison-Wesley}, 73 | year = {1986}, 74 | address = {Reading, Mass}, 75 | isbn = {020112078X} 76 | } 77 | 78 | @book{the-cpp-programming-language-2nd, 79 | author = {Stroustrup, Bjarne}, 80 | title = {The C++ programming language}, 81 | publisher = {Addison-Wesley}, 82 | year = {1991}, 83 | address = {Reading, Mass}, 84 | isbn = {0201539926} 85 | } 86 | 87 | @book{the-cpp-programming-language-3rd, 88 | author = {Stroustrup, Bjarne}, 89 | title = {The C++ programming language}, 90 | publisher = {Addison-Wesley}, 91 | year = {1997}, 92 | address = {Reading, Mass}, 93 | isbn = {0201889544} 94 | } 95 | 96 | @book{the-cpp-programming-language-se, 97 | author = {Stroustrup, Bjarne}, 98 | title = {The C++ programming language}, 99 | publisher = {Addison-Wesley}, 100 | year = {2000}, 101 | address = {Boston}, 102 | isbn = {0201700735} 103 | } 104 | 105 | @book{the-cpp-programming-language-4th, 106 | author = {Stroustrup, Bjarne}, 107 | title = {The C++ programming language}, 108 | publisher = {Addison-Wesley}, 109 | year = {2013}, 110 | address = {Upper Saddle River, NJ}, 111 | isbn = {0321563840} 112 | } 113 | 114 | @misc{2021-annual-cpp-developer-survey, 115 | author = {Standard C++ Foundation}, 116 | title = {\emph{2021 Annual C++ Developer Survey ``Lite''}}, 117 | year = {2021}, 118 | note = {\url{https://isocpp.org/files/papers/CppDevSurvey-2021-04-summary.pdf}} 119 | } 120 | 121 | @misc{compile-health, 122 | author = {Trettner, Philip}, 123 | title = {\emph{C++ Compile Health Watchdog}}, 124 | year = {2020}, 125 | howpublished = {\url{https://artificial-mind.net/projects/compile-health/}} 126 | } 127 | 128 | @misc{stl-header-heft, 129 | author = {Douglas, Niall}, 130 | title = {\emph{STL Header Heft}}, 131 | year = {2020}, 132 | howpublished = {\url{https://github.com/ned14/stl-header-heft}} 133 | } 134 | 135 | @techreport{pcg, 136 | title = {\emph{PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation}}, 137 | author = {Melissa E. O'Neill}, 138 | institution = {Harvey Mudd College}, 139 | address = {Claremont, CA}, 140 | number = {HMC-CS-2014-0905}, 141 | year = {2014}, 142 | month = Sep, 143 | xurl = {https://www.cs.hmc.edu/tr/hmc-cs-2014-0905.pdf}, 144 | } 145 | 146 | @misc{beware-of-copies-initializer-list, 147 | author = {Tristan Brindle}, 148 | title = {\emph{Beware of copies with std::initializer\_list!}}, 149 | year = {2020}, 150 | howpublished = {\url{https://tristanbrindle.com/posts/beware-copies-initializer-list}} 151 | } 152 | 153 | @misc{tango-icon-theme, 154 | author = {Tango Project contributors}, 155 | title = {\emph{Tango Desktop Project}}, 156 | year = {Since 2005}, 157 | howpublished = {\url{https://tango.freedesktop.org}} 158 | } 159 | 160 | @misc{gif87a, 161 | author = {Compuserve, Incorporated}, 162 | title = {\emph{Graphics Interchange Format Specifications}}, 163 | year = {1987}, 164 | howpublished = {\url{https://www.w3.org/Graphics/GIF/spec-gif87.txt}} 165 | } 166 | -------------------------------------------------------------------------------- /counting-in-c++.tex: -------------------------------------------------------------------------------- 1 | \documentclass{book} 2 | 3 | \usepackage[english]{babel} 4 | \usepackage[normalem]{ulem} 5 | \usepackage{cite} 6 | \usepackage{enumitem} 7 | \usepackage[dvipsnames]{xcolor} 8 | \usepackage{fontawesome} 9 | \usepackage{times} 10 | \usepackage[marginparwidth=2.5cm]{geometry} 11 | \usepackage{graphicx} 12 | \usepackage[colorlinks=true,allcolors=Blue]{hyperref} 13 | \usepackage{bookmark} 14 | \usepackage[T1]{fontenc} 15 | \usepackage{marginnote} 16 | \usepackage{mdframed} 17 | \usepackage{sectsty} 18 | \usepackage[thicklines]{cancel} 19 | \usepackage[nottoc,numbib]{tocbibind} 20 | \usepackage[parfill]{parskip} 21 | 22 | % Write C++XX using the format from cppreference.com: capital C, no 23 | % dash nor space. 24 | \newcommand{\cpp}[1]{C++{#1}} 25 | \newcommand{\Cpp}[1]{C++{#1}} 26 | 27 | \newcommand{\cppheader}[1]{\textless #1\textgreater} 28 | 29 | \newcommand{\aref}[1]{[\ref{#1}]} 30 | 31 | \title{Counting from 98 to 14 \\ in \Cpp{}} 32 | \author{Julien Jorge} 33 | \newcommand{\version}{@CMAKE_PROJECT_VERSION@} 34 | 35 | \input{style/code-listings} 36 | 37 | \newcommand{\code}[1]{{\tt #1}} 38 | 39 | \newcommand{\marginheader}[1]{% 40 | \marginnote{% 41 | \begin{center}% 42 | \includegraphics[width=0.5\linewidth]{assets/header-icon.pdf} \\ 43 | \footnotesize #1 44 | \end{center}% 45 | }[-1.5em]% 46 | } 47 | 48 | \newcommand{\problemtitle}{\subsubsection{What was the problem}} 49 | \newcommand{\solutiontitle}{\subsubsection{How the Problem is Solved}} 50 | 51 | \newenvironment{guideline} 52 | { 53 | \begin{mdframed}[ 54 | topline=false, 55 | rightline=false, 56 | bottomline=false, 57 | linewidth=1pt, 58 | frametitle={Guideline} 59 | ] 60 | } 61 | { 62 | \end{mdframed} 63 | } 64 | 65 | \newenvironment{pitfall} 66 | { 67 | \begin{mdframed}[ 68 | topline=false, 69 | rightline=false, 70 | bottomline=false, 71 | linewidth=1pt, 72 | frametitle={It's a trap} 73 | ] 74 | } 75 | { 76 | \end{mdframed} 77 | } 78 | 79 | \begin{document} 80 | \allsectionsfont{\sffamily} 81 | 82 | \frontmatter 83 | \input{parts/title-page} 84 | 85 | \cleardoublepage 86 | \pdfbookmark{\contentsname}{toc} 87 | \tableofcontents 88 | 89 | \input{parts/preface} 90 | 91 | 92 | \mainmatter 93 | \input{parts/cpp-general} 94 | \input{parts/11} 95 | \input{parts/14} 96 | 97 | \bibliographystyle{alpha} 98 | \bibliography{bibliography.bib} 99 | 100 | \appendix 101 | \input{parts/license.tex} 102 | 103 | \end{document} 104 | -------------------------------------------------------------------------------- /examples/constexpr/constexpr-11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | constexpr int popcount(unsigned n) 4 | { 5 | return (n == 0) ? 0 : ((n & 1) + popcount(n >> 1)); 6 | } 7 | 8 | int main(int argc, char**) 9 | { 10 | int array[popcount(45)]; 11 | printf("%d\n", popcount(argc)); 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /examples/constexpr/constexpr-14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | constexpr int popcount(unsigned n) 4 | { 5 | int result = 0; 6 | 7 | for (; n != 0; n >>= 1) 8 | if ((n & 1) != 0) 9 | ++result; 10 | 11 | return result; 12 | } 13 | 14 | int main(int argc, char**) 15 | { 16 | int array[popcount(45)]; 17 | printf("%d\n", popcount(argc)); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /examples/constexpr/constexpr-98.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct popcount_t; 5 | 6 | template<> 7 | struct popcount_t<0> 8 | { 9 | enum { value = 0 }; 10 | }; 11 | 12 | template 13 | struct popcount_t 14 | { 15 | enum 16 | { 17 | value = (N & 1) + popcount_t<(N >> 1)>::value 18 | }; 19 | }; 20 | 21 | int popcount(unsigned n) 22 | { 23 | return (n == 0) ? 0 : ((n & 1) + popcount(n >> 1)); 24 | } 25 | 26 | int main(int argc, char**) 27 | { 28 | int array[popcount_t<45>::value]; 29 | printf("%d\n", popcount(argc)); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /examples/extern-template/bar-11.cpp: -------------------------------------------------------------------------------- 1 | #include "factorial-11.hpp" 2 | 3 | int bar(int i) 4 | { 5 | return factorial(i); 6 | } 7 | -------------------------------------------------------------------------------- /examples/extern-template/bar-98.cpp: -------------------------------------------------------------------------------- 1 | // bar-98.cpp 2 | #include "factorial-98.hpp" 3 | 4 | int bar(int i) 5 | { 6 | return factorial(i); 7 | } 8 | -------------------------------------------------------------------------------- /examples/extern-template/factorial-11.cpp: -------------------------------------------------------------------------------- 1 | // factorial-11.cpp 2 | #include "factorial-11.hpp" 3 | 4 | template int factorial(int); 5 | -------------------------------------------------------------------------------- /examples/extern-template/factorial-11.hpp: -------------------------------------------------------------------------------- 1 | // factorial-11.hpp 2 | #pragma once 3 | 4 | template 5 | T factorial(T n) 6 | { 7 | T r = 1; 8 | 9 | for (T i = 1; i <= n; ++i) 10 | r += r * i; 11 | 12 | return r; 13 | } 14 | 15 | extern template int factorial(int); 16 | -------------------------------------------------------------------------------- /examples/extern-template/factorial-98.hpp: -------------------------------------------------------------------------------- 1 | // factorial-98.hpp 2 | #pragma once 3 | 4 | template 5 | T factorial(T n) 6 | { 7 | T r = 1; 8 | 9 | for (T i = 1; i <= n; ++i) 10 | r += r * i; 11 | 12 | return r; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /examples/extern-template/foo-11.cpp: -------------------------------------------------------------------------------- 1 | #include "factorial-11.hpp" 2 | 3 | int foo(int i) 4 | { 5 | return factorial(i); 6 | } 7 | -------------------------------------------------------------------------------- /examples/extern-template/foo-98.cpp: -------------------------------------------------------------------------------- 1 | // foo-98.cpp 2 | #include "factorial-98.hpp" 3 | 4 | int foo(int i) 5 | { 6 | return factorial(i); 7 | } 8 | -------------------------------------------------------------------------------- /examples/extern-template/main.cpp: -------------------------------------------------------------------------------- 1 | int foo(int i); 2 | int bar(int i); 3 | 4 | int main(int argc, char** argv) 5 | { 6 | foo(argc); 7 | bar(argc); 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/nullptr/nullptr-11.cpp: -------------------------------------------------------------------------------- 1 | void foo(int) {} 2 | void foo(int*) {} 3 | 4 | int main(int argc, char** argv) 5 | { 6 | foo(nullptr); 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /examples/nullptr/nullptr-98.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void foo(int) {} 4 | void foo(int*) {} 5 | 6 | int main(int argc, char** argv) 7 | { 8 | foo(NULL); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/reference-wrapper/capacity_tracker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct capacity_tracker 6 | { 7 | // Decrease the capacity by the given value if it is not too much. Returns 8 | // false if the capacity has been decreased, true otherwise. 9 | // 10 | // Yes, the meaning of the return value is crap. It is just for the example, 11 | // so it matches the expectations of std::find() below. Don't do that at home. 12 | bool operator()(int value) 13 | { 14 | if (capacity < value) 15 | return true; 16 | 17 | capacity -= value; 18 | return false; 19 | } 20 | 21 | int capacity; 22 | }; 23 | 24 | int main() 25 | { 26 | capacity_tracker tracker = { 10 }; 27 | const int values[] = { 3, 1, 2, 4, 5, 8, 6, 7 }; 28 | 29 | // Decrease the capacity by the given values until the capacity becomes lower 30 | // than the value. The capacity is decreased along the way and thus reflects 31 | // the final value at the end. 32 | // 33 | // Even though the returned value is correct, the final capacity in the 34 | // tracker will be incorrect. Indeed, it is copied in the call to 35 | // std::find_if(), so any change has no impact on the local variable. 36 | const int* overflow = std::find_if(values, values + 8, tracker); 37 | 38 | printf 39 | ("remaining capacity: %d, overflow with %d\n", tracker.capacity, *overflow); 40 | 41 | // This one will work correctly, because a reference to the tracker is passed 42 | // to std::find_if. 43 | overflow = std::find_if(values, values + 8, std::ref(tracker)); 44 | 45 | printf 46 | ("remaining capacity: %d, overflow with %d\n", tracker.capacity, *overflow); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /examples/static-assert/even_sized_array-11.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct even_sized_array 3 | { 4 | // We can also put a message to repeat the condition, like 5 | // professionals. Don't forget the exclamation mark to 6 | // show it is serious. 7 | static_assert(N % 2 == 0, "The size must be even!"); 8 | typedef T type[N]; 9 | }; 10 | 11 | // So much less code <3 12 | void test() 13 | { 14 | even_sized_array::type ok; 15 | even_sized_array::type nok; 16 | } 17 | -------------------------------------------------------------------------------- /examples/static-assert/even_sized_array-98.cpp: -------------------------------------------------------------------------------- 1 | // The third template argument is expected to receive a flag 2 | // telling if N is even (i.e. valid). 3 | template 4 | struct even_sized_array_impl; 5 | 6 | // And we implement this type only if the flag is true. 7 | template 8 | struct even_sized_array_impl 9 | { 10 | typedef T type[N]; 11 | }; 12 | 13 | template 14 | struct even_sized_array 15 | { 16 | // Now we trigger the check by actually instantiating the 17 | // helper type, hoping that the flag will be true. 18 | typedef 19 | typename even_sized_array_impl::type 20 | type; 21 | }; 22 | 23 | void test() 24 | { 25 | even_sized_array::type ok; 26 | even_sized_array::type nok; 27 | } 28 | -------------------------------------------------------------------------------- /examples/thread/flood.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct flood_state 6 | { 7 | int counter; 8 | std::mutex mutex; 9 | }; 10 | 11 | int main() 12 | { 13 | flood_state state; 14 | state.counter = 0; 15 | 16 | // std::thread's constructor takes the function to be executed in the thread 17 | // as its argument. Here we use a lambda @\aref{sec:lambda}@. 18 | std::thread increase 19 | ([&state]() -> void 20 | { 21 | while (true) 22 | { 23 | // Wait until the mutex is available and lock it. std::unique_lock 24 | // automatically unlocks it when going out of scope. Good old RAII. 25 | const std::unique_lock lock(state.mutex); 26 | ++state.counter; 27 | } 28 | }); 29 | std::thread decrease 30 | ([&state]() -> void 31 | { 32 | while (true) 33 | { 34 | int counter; 35 | 36 | { 37 | // We limit the scope of the lock to the access to the shared 38 | // state. 39 | std::unique_lock lock(state.mutex); 40 | counter = state.counter; 41 | state.counter -= 2; 42 | } 43 | 44 | // This is executed after the release of the mutex, so the state can 45 | // be accessed while printing. 46 | printf("%d\n", counter); 47 | } 48 | }); 49 | 50 | // std::thread::join() waits until the thread is over (which will not happen 51 | // in our case as nothing breaks outside the infinite loops. 52 | increase.join(); 53 | decrease.join(); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /examples/tuple/binding.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // This structure is here to "store" a sequence of integers in its template 5 | // parameters. There is nothing like that in C++11 but it is already available 6 | // in C++14 @\ref{sec:integer-sequence}@. 7 | template 8 | struct integer_sequence {}; 9 | 10 | // This one is used to create a sequence of N consecutive integers, from 0 to 11 | // N-1, given N. 12 | // 13 | // Remaining is the number of integers that still have to be generated. 14 | // Computed is the sequence we have computed so far. 15 | template 16 | struct make_integer_sequence; 17 | 18 | template 19 | struct make_integer_sequence<0, Computed...> 20 | { 21 | using type = integer_sequence; 22 | }; 23 | 24 | template 25 | struct make_integer_sequence 26 | { 27 | using type = 28 | typename make_integer_sequence 29 | < 30 | Remaining - 1, 31 | Remaining - 1, 32 | Computed... 33 | >::type; 34 | }; 35 | 36 | // The call_helper will help us to get the elements of a tuple, because we 37 | // cannot get them by type. 38 | template 39 | struct call_helper; 40 | 41 | template 42 | struct call_helper> 43 | { 44 | template 45 | static void call(F&& function, std::tuple& arguments) 46 | { 47 | // Here we unpack I... to get the arguments from the tuple. 48 | // See @\aref{variadic-template}@. 49 | // 50 | // Note that it does not work with member functions, as they require another 51 | // call syntax. This is left as an exercise for the reader. 52 | function(std::get(arguments)...); 53 | } 54 | }; 55 | 56 | // A binding is a function object that can be called with no arguments and that, 57 | // when called, will pass the arguments given to its constructor to the function 58 | // given to its constructor. 59 | template 60 | struct binding 61 | { 62 | binding(F&& f, Args&&... arguments) 63 | : m_function(std::forward(f)), 64 | m_arguments(std::forward(arguments)...) 65 | {} 66 | 67 | void operator()() 68 | { 69 | // Here there is no way to get the elements from the m_arguments tuple by 70 | // unpacking Args..., so we indirectly build an integer pack that will 71 | // ultimately be used to call std::get(m_arguments) for each I. 72 | call_helper 73 | < 74 | typename make_integer_sequence::type 75 | >::call 76 | (m_function, m_arguments); 77 | } 78 | 79 | private: 80 | F m_function; 81 | std::tuple m_arguments; 82 | }; 83 | 84 | // This function is just here to build a binding without specifying all its 85 | // template parameters. 86 | template 87 | binding bind(F&& f, Args&&... arguments) 88 | { 89 | return 90 | binding 91 | (std::forward(f), std::forward(arguments)...); 92 | } 93 | 94 | // The function that will be bound. 95 | void print(int a, int b) 96 | { 97 | printf("%d, %d\n", a, b); 98 | } 99 | 100 | int main() 101 | { 102 | // This creates the binding. Is it a valid use case of auto @\aref{auto}@? 103 | auto f(bind(&print, 24, 42)); 104 | 105 | // And now we can call print with the provided arguments. 106 | f(); 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /examples/type-traits/main-11.cpp: -------------------------------------------------------------------------------- 1 | #include "mix-11.hpp" 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | printf("%f\n", mix(1.f, 3.f, 0.5f)); 8 | printf("%f\n", mix(1.d, 3.d, 0.5d)); 9 | // printf("%d\n", mix(1, 3, 2)); 10 | 11 | return 0; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /examples/type-traits/main-98.cpp: -------------------------------------------------------------------------------- 1 | #include "mix-98.hpp" 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | printf("%f\n", mix(1.f, 3.f, 0.5f)); 8 | printf("%f\n", mix(1.d, 3.d, 0.5d)); 9 | // printf("%d\n", mix(1, 3, 2)); 10 | 11 | return 0; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /examples/type-traits/mix-11.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | typename std::enable_if::value, T>::type 5 | mix(T a, T b, T r) 6 | { 7 | return r * a + (1 - r) * b; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /examples/type-traits/mix-98.hpp: -------------------------------------------------------------------------------- 1 | // This struct declares a type identical to T if and only if T is 2 | // a float-like type. We are going to specialize it only for the 3 | // valid types. For the other types, the missing type declaration 4 | // in the struct will trigger a substitution failure. 5 | template 6 | struct only_if_float_like; 7 | 8 | template<> 9 | struct only_if_float_like 10 | { 11 | typedef float type; 12 | }; 13 | 14 | template<> 15 | struct only_if_float_like 16 | { 17 | typedef double type; 18 | }; 19 | 20 | template 21 | typename only_if_float_like::type mix(T a, T b, T r) 22 | { 23 | return r * a + (1 - r) * b; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /examples/uniform-initialization/struct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct foo_struct 5 | { 6 | int a; 7 | int b; 8 | }; 9 | 10 | struct foo_constructor 11 | { 12 | foo_constructor(int v1, int v2) 13 | // Note that arguments and fields are swapped. 14 | : a(v2), b(v1) 15 | {} 16 | 17 | int a; 18 | int b; 19 | }; 20 | 21 | struct foo_initializer_list 22 | { 23 | foo_initializer_list(int v1, int v2) 24 | // Note that arguments and fields are still swapped. 25 | : a(v2), b(v1) 26 | {} 27 | 28 | // An initializer list allows to construct an object using an aggregate-like 29 | // syntax. We will come back to it in @\ref{initializer-list}@ :) 30 | foo_initializer_list(const std::initializer_list& i) 31 | // Note that the fields are set to the same value. 32 | : a(*i.begin()), 33 | b(a) 34 | {} 35 | 36 | int a; 37 | int b; 38 | }; 39 | 40 | template 41 | void build_foo(int x, int y) 42 | { 43 | Foo foo{x, y}; 44 | 45 | printf(".a=%d, .b=%d\n", foo.a, foo.b); 46 | } 47 | 48 | int main() 49 | { 50 | build_foo(24, 42); 51 | build_foo(24, 42); 52 | build_foo(24, 42); 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /examples/variable-template/main-11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | struct popcount; 5 | 6 | template<> 7 | struct popcount<0> 8 | { 9 | static constexpr unsigned value = 0; 10 | }; 11 | 12 | template 13 | struct popcount 14 | { 15 | static constexpr unsigned value = N % 2 + popcount<(N >> 1)>::value; 16 | }; 17 | 18 | int main() 19 | { 20 | // In order to actually do the computation, we have to instantiate 21 | // a type and get the value declared inside this type. 22 | printf("%d\n", popcount<24>::value); 23 | } 24 | -------------------------------------------------------------------------------- /examples/variable-template/main-14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // This is a variable, whose value depends upon a template argument. 4 | template 5 | unsigned popcount = N % 2 + popcount<(N >> 1)>; 6 | 7 | // The variable can be specialized too! 8 | template<> 9 | unsigned popcount<0> = 0; 10 | 11 | int main() 12 | { 13 | // Here we can use a variable to represent a value. Much more clear. 14 | printf("%d\n", popcount<24>); 15 | } 16 | -------------------------------------------------------------------------------- /examples/variadic-template/callbacks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void on_event() 4 | { 5 | printf("on_event\n"); 6 | } 7 | 8 | void also_on_event() 9 | { 10 | printf("also_on_event\n"); 11 | } 12 | 13 | void on_message(const char* message) 14 | { 15 | printf("on_message: %s\n", message); 16 | } 17 | 18 | void also_on_message(const char* message) 19 | { 20 | printf("also_on_message: %s\n", message); 21 | } 22 | 23 | void on_long_message(const char* message_1, const char* message_2) 24 | { 25 | printf("on_long_message: %s, %s\n", message_1, message_2); 26 | } 27 | 28 | void also_on_long_message(const char* message_1, const char* message_2) 29 | { 30 | printf("also_on_long_message: %s, %s\n", message_1, message_2); 31 | } 32 | -------------------------------------------------------------------------------- /examples/variadic-template/collect_type_names.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | void collect_type_names() 6 | { 7 | const char* names[] = {typeid(T).name()...}; 8 | 9 | for (const char* name : names) 10 | printf("%s\n", name); 11 | } 12 | 13 | int main() 14 | { 15 | collect_type_names(); 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /examples/variadic-template/dispatcher-11.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // The template accepts any number of arguments. 6 | template 7 | struct dispatcher 8 | { 9 | // We can list the template parameters by appending '...'. 10 | typedef void (*function_type)(Args...); 11 | 12 | void queue(function_type f) 13 | { 14 | m_scheduled.push_back(f); 15 | } 16 | 17 | // args represent any sequence of arguments here. 18 | template 19 | void dispatch(A&&... args) 20 | { 21 | const std::size_t count = m_scheduled.size(); 22 | 23 | // Then we can list the arguments by appending '...' 24 | // to the function argument. 25 | for (std::size_t i(0); i != count; ++i) 26 | m_scheduled[i](args...); 27 | } 28 | 29 | private: 30 | std::vector m_scheduled; 31 | }; 32 | -------------------------------------------------------------------------------- /examples/variadic-template/dispatcher-98.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dispatcher_impl_0.hpp" 4 | #include "dispatcher_impl_1.hpp" 5 | #include "dispatcher_impl_2.hpp" 6 | 7 | template 8 | struct dispatcher: dispatcher_impl 9 | {}; 10 | -------------------------------------------------------------------------------- /examples/variadic-template/dispatcher_impl.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | struct dispatcher_impl; 5 | 6 | -------------------------------------------------------------------------------- /examples/variadic-template/dispatcher_impl_0.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dispatcher_impl.hpp" 4 | 5 | #include 6 | 7 | template<> 8 | struct dispatcher_impl 9 | { 10 | typedef void (*function_type)(); 11 | 12 | void queue(function_type f) 13 | { 14 | m_scheduled.push_back(f); 15 | } 16 | 17 | void dispatch() 18 | { 19 | const std::size_t count = m_scheduled.size(); 20 | 21 | for (std::size_t i(0); i != count; ++i) 22 | m_scheduled[i](); 23 | } 24 | 25 | private: 26 | // The functions that will be called on the next dispatch. 27 | std::vector m_scheduled; 28 | }; 29 | -------------------------------------------------------------------------------- /examples/variadic-template/dispatcher_impl_1.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dispatcher_impl.hpp" 4 | 5 | #include 6 | 7 | template 8 | struct dispatcher_impl 9 | { 10 | typedef void (*function_type)(Arg); 11 | 12 | void queue(function_type f) 13 | { 14 | m_scheduled.push_back(f); 15 | } 16 | 17 | template 18 | void dispatch(A a) 19 | { 20 | const std::size_t count = m_scheduled.size(); 21 | 22 | for (std::size_t i(0); i != count; ++i) 23 | m_scheduled[i](a); 24 | } 25 | 26 | private: 27 | // The functions that will be called on the next dispatch. 28 | std::vector m_scheduled; 29 | }; 30 | -------------------------------------------------------------------------------- /examples/variadic-template/dispatcher_impl_2.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dispatcher_impl.hpp" 4 | 5 | #include 6 | 7 | template 8 | struct dispatcher_impl 9 | { 10 | typedef void (*function_type)(Arg1, Arg2); 11 | 12 | void queue(function_type f) 13 | { 14 | m_scheduled.push_back(f); 15 | } 16 | 17 | template 18 | void dispatch(A1 a1, A2 a2) 19 | { 20 | const std::size_t count = m_scheduled.size(); 21 | 22 | for (std::size_t i(0); i != count; ++i) 23 | m_scheduled[i](a1, a2); 24 | } 25 | 26 | private: 27 | // The functions that will be called on the next dispatch. 28 | std::vector m_scheduled; 29 | }; 30 | -------------------------------------------------------------------------------- /examples/variadic-template/main-11.cpp: -------------------------------------------------------------------------------- 1 | #include "dispatcher-11.hpp" 2 | 3 | // Some functions that will be called by our dispatcher 4 | void on_event(); 5 | void also_on_event(); 6 | void on_message(const char* message); 7 | void also_on_message(const char* message); 8 | void on_long_message(const char* message_1, const char* message_2); 9 | void also_on_long_message(const char* message_1, const char* message_2); 10 | 11 | int main() 12 | { 13 | // A dispatcher with no arguments and two scheduled functions. 14 | dispatcher<> zero; 15 | zero.queue(&on_event); 16 | zero.queue(&also_on_event); 17 | 18 | // A dispatcher with one argument and two scheduled functions. 19 | dispatcher one; 20 | one.queue(&on_message); 21 | one.queue(&also_on_message); 22 | 23 | // A dispatcher with two argument and two scheduled functions. 24 | dispatcher two; 25 | two.queue(&on_long_message); 26 | two.queue(&also_on_long_message); 27 | 28 | // Now we trigger the calls with the given arguments. 29 | zero.dispatch(); 30 | one.dispatch("hello"); 31 | two.dispatch("hello", "world"); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /examples/variadic-template/main-98.cpp: -------------------------------------------------------------------------------- 1 | #include "dispatcher-98.hpp" 2 | 3 | // Some functions that will be called by our dispatcher 4 | void on_event(); 5 | void also_on_event(); 6 | void on_message(const char* message); 7 | void also_on_message(const char* message); 8 | void on_long_message(const char* message_1, const char* message_2); 9 | void also_on_long_message(const char* message_1, const char* message_2); 10 | 11 | int main() 12 | { 13 | // A dispatcher with no arguments and two scheduled functions. 14 | dispatcher<> zero; 15 | zero.queue(&on_event); 16 | zero.queue(&also_on_event); 17 | 18 | // A dispatcher with one argument and two scheduled functions. 19 | dispatcher one; 20 | one.queue(&on_message); 21 | one.queue(&also_on_message); 22 | 23 | // A dispatcher with two argument and two scheduled functions. 24 | dispatcher two; 25 | two.queue(&on_long_message); 26 | two.queue(&also_on_long_message); 27 | 28 | // Now we trigger the calls with the given arguments. 29 | zero.dispatch(); 30 | one.dispatch("hello"); 31 | two.dispatch("hello", "world"); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /html-cleanup/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(LibXml2 REQUIRED) 2 | 3 | add_executable(html-cleanup 4 | main.cpp 5 | ) 6 | 7 | set_property(TARGET html-cleanup PROPERTY CXX_STANDARD 17) 8 | 9 | target_link_libraries(html-cleanup LibXml2::LibXml2) 10 | 11 | set(html_cleanup "${CMAKE_CURRENT_BINARY_DIR}/html-cleanup" PARENT_SCOPE) 12 | -------------------------------------------------------------------------------- /html-preclean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -euo pipefail 4 | 5 | mv counting-in-cpp/counting-in-c++.html counting-in-cpp/index.html 6 | 7 | sed "s/\(Naming quality: .*\).*\(<\/span>. Would have put zero stars\)/\1★☆☆☆☆\2/g" -i counting-in-cpp/counting-in-c++su12.html 8 | 9 | tidy --hide-comments yes --quote-nbsp no -modify -quiet counting-in-cpp/*.html \ 10 | || true 11 | 12 | -------------------------------------------------------------------------------- /make4ht.cfg: -------------------------------------------------------------------------------- 1 | \Preamble{xhtml,ext=html,charset="utf-8"} 2 | \Configure{TITLE+}{Counting in C++ from 98 to 14 | Julien Jorge} 3 | \begin{document} 4 | \let\contentsname\empty 5 | \EndPreamble 6 | -------------------------------------------------------------------------------- /parts/11.tex: -------------------------------------------------------------------------------- 1 | \chapter{Nice Things from C++11} 2 | 3 | Ah, \cpp11, the long awaited update of the language. There was so much 4 | hope in it! Just imagine, back in the day the language had no 5 | automatic dynamic memory management, and not even a hash table in the 6 | standard library… in the year 2000! 7 | 8 | At that time we were trying to compensate for the lack of features 9 | with Boost, eagerly waiting for the ever postponed upcoming \cpp 0x 10 | that would change everything. We were going to have modules! And 11 | concepts too! 12 | 13 | Looking back into these years, I am quite happy that the committee 14 | dropped the most complex features to finally publish a new version, 15 | because most of the parts that were ready are quite awesome. 16 | 17 | \section{At the Language Level} 18 | \input{parts/11/range-based-for-loops} 19 | \input{parts/11/nullptr} 20 | \input{parts/11/scoped-enumerations} 21 | \input{parts/11/constexpr} 22 | \input{parts/11/uniform-initialization} 23 | \input{parts/11/static-assert} 24 | 25 | \input{parts/11/lambdas} 26 | \input{parts/11/decltype} 27 | \input{parts/11/auto} 28 | \input{parts/11/rvalue-reference} 29 | 30 | \section{Move Semantics} 31 | \input{parts/11/move} 32 | 33 | \section{Template-Related Features} 34 | \input{parts/11/template-aliases} 35 | \input{parts/11/extern-template} 36 | \input{parts/11/variadic-template} 37 | 38 | \section{Objects and Classes} 39 | \input{parts/11/delegated-constructors} 40 | \input{parts/11/deleted-constructors} 41 | \input{parts/11/defaulted-constructors} 42 | \input{parts/11/override-and-final} 43 | \input{parts/11/using-parent-function} 44 | 45 | \section{In the Standard Library} 46 | \input{parts/11/free-begin} 47 | \input{parts/11/prev-next} 48 | \input{parts/11/array} 49 | \input{parts/11/random} 50 | \input{parts/11/smart-pointers} 51 | \input{parts/11/initializer-list} 52 | \input{parts/11/thread} 53 | \input{parts/11/tuple} 54 | \input{parts/11/bind} 55 | \input{parts/11/reference-wrapper} 56 | \input{parts/11/function} 57 | \input{parts/11/hash-table} 58 | \input{parts/11/type-traits} 59 | 60 | % chrono is missing 61 | % future is missing 62 | 63 | \section{Miscellaneous} 64 | \input{parts/11/miscellaneous} 65 | 66 | % member initialization 67 | % inline namespaces 68 | % trailing return type 69 | -------------------------------------------------------------------------------- /parts/11/array.tex: -------------------------------------------------------------------------------- 1 | \subsection{Arrays} 2 | 3 | \problemtitle 4 | 5 | How do we usually pass a raw array to a function in \cpp? By passing 6 | both a pointer to the first element and the number of elements, that 7 | is how. 8 | 9 | And when we need to copy such array, or to return such array from a 10 | function, it becomes quite tricky. 11 | 12 | \begin{lstlisting} 13 | void replace_zeros_copy(int* out, int* in, std::size_t size, int r) 14 | { 15 | // Can I trust the caller that the target array is large enough to 16 | // store the result? Is it a valid use case to pass null pointers 17 | // here? So many questions :( 18 | 19 | std::transform 20 | (in, in + size, out, 21 | [r](int v) -> int 22 | { 23 | return (v == 0) ? r : v; 24 | }); 25 | } 26 | 27 | // We certainly cannot properly return a raw array unless we use 28 | // some dynamic allocation or other techniques with their own 29 | // problems. 30 | int* replace_zeros_copy(int* array, std::size_t size, int r) { /* … */ } 31 | \end{lstlisting} 32 | 33 | \solutiontitle 34 | 35 | \marginheader{}% 36 | % 37 | With \cpp11 came \code{std::array} a template type to be used as an 38 | alternative to raw arrays, with two parameters: the type of the 39 | elements and their count. 40 | 41 | \begin{lstlisting} 42 | template 43 | void replace_zeros_copy 44 | (@\emcode{std::array}@& out, const @\emcode{std::array}@& in, int r) 45 | { 46 | // Forget about the null pointers problem and the size issues, 47 | // everything fits perfectly here. 48 | 49 | std::transform 50 | (in.begin(), in.end(), out.begin(), 51 | [r](int v) -> int 52 | { 53 | return (v == 0) ? r : v; 54 | }); 55 | } 56 | 57 | // We can also directly return the array. 58 | template 59 | @\emcode{std::array}@ replace_zeros_copy(const @\emcode{std::array}@& array, int r) 60 | { 61 | std::array result; 62 | replace_zeros_copy(result, array, r); 63 | return result; 64 | } 65 | \end{lstlisting} 66 | 67 | An \code{std::array} is as cheap as a raw array. It has no fancy 68 | constructor or any subtleties, and I can think of only two downsides 69 | to using it: 70 | \begin{enumerate} 71 | \item the cost of including an extra header \cite{compile-health} 72 | \cite{stl-header-heft}, not negligible in this case as 73 | \cppheader{array} pulls \cppheader{utility} and more, 74 | \item the need to carry the size as a template parameter. 75 | \end{enumerate} 76 | 77 | \begin{guideline} 78 | Because of the downsides associated with the type and its header, 79 | using \code{std::array} should always be preceded by two 80 | considerations: 81 | 82 | \begin{enumerate} 83 | \item Will the header propagate to many files? 84 | \item Will I have to templatize everything? 85 | \item Should I implement iterator-based algorithms instead? 86 | \end{enumerate} 87 | \end{guideline} 88 | 89 | Also, note that \code{std::array} is not a fixed-capacity vector. All 90 | its entries are default initialized as soon as the array is 91 | constructed. So if it contains complex types, it means that the 92 | default constructor of this type is called for each entry. 93 | -------------------------------------------------------------------------------- /parts/11/auto.tex: -------------------------------------------------------------------------------- 1 | \subsection{Auto} 2 | \label{auto} 3 | 4 | Section \ref{decltype} explained how one could deduce the type of an 5 | expression with \code{decltype} to set the type of a local variable 6 | to match the type of an expression. 7 | 8 | Now what about storing a lambda in a local variable, what would be the 9 | type of the variable? As seen in \ref{lambdas-internals}, the type of 10 | the lambda is generated by the compiler, and thus out of reach for the 11 | programmer. The solution is then found in the \code{auto} keyword, 12 | introduced in \cpp11. 13 | 14 | \begin{lstlisting} 15 | bool has_string_of_size 16 | (const std::vector& strings, std::size_t s) 17 | { 18 | @\emcode{auto}@ predicate = 19 | [=](const std::string& string) -> bool 20 | { 21 | return string.size() == s; 22 | }; 23 | 24 | return 25 | std::find_if(strings.begin(), strings.end(), predicate) 26 | != strings.end(); 27 | } 28 | \end{lstlisting} 29 | 30 | %------------------------------------------------------------------------------- 31 | \subsubsection{Auto as a Type Placeholder} 32 | 33 | The \code{auto} keyword tells the compiler to deduce the actual type 34 | of a variable from whatever is assigned to it. It can be used as long 35 | as there is an expression the compiler can use to find the type. It 36 | can be augmented with \code{const} or \code{\&}. 37 | 38 | A typical use is for iterating over an associative container in a for 39 | loop: 40 | 41 | \begin{lstlisting} 42 | template 43 | void for_each_entry(const std::map& m, F& f) 44 | { 45 | for (const auto& e : m) 46 | f(e.first, e.second); 47 | } 48 | \end{lstlisting} 49 | 50 | In the spirit of \ref{range-based-for-loops}, the type of \code{e} is 51 | deduced to \code{std::map\textless{}int, 52 | int\textgreater::value\_type}, to which are added the \code{const} 53 | and the \code{\&}. 54 | 55 | When used as a return type, the \code{auto} keyword allows to defer 56 | the declaration of the actual return type after the argument list. For 57 | example, if we don't know what is the type but we know it is exactly 58 | the one of a given expression, we can combine this with 59 | \code{decltype}: 60 | 61 | \begin{lstlisting} 62 | template 63 | auto indirect_call(F&& f) -> decltype(f()) 64 | { 65 | return f(); 66 | } 67 | \end{lstlisting} 68 | 69 | %------------------------------------------------------------------------------- 70 | \subsubsection{When not to Use \code{auto}} 71 | 72 | It is tempting to use the \code{auto} keyword everywhere, especially 73 | for programmers coming from loosely typed languages such as Python or 74 | JavaScript. Moreover, using \code{auto} gives the satisfying feeling 75 | of writing seemingly ``generic'' code that can work with whatever type 76 | is deduced. 77 | 78 | In practice, the use of this keyword has lead to very painful to read 79 | code, where nothing can be understood without going through every 80 | expression assigned to an \code{auto} variable, and where entire 81 | functions have to be interpreted to eventually find the returned 82 | type. This is a very high load to pass to the next reader. 83 | 84 | \begin{guideline} 85 | Mind the next reader; write what you mean. 86 | 87 | Declaring a variable or a function as \code{auto} is like writing an 88 | innuendo, and innuendos make the communication more difficult; if you 89 | see what I mean. 90 | 91 | As a rule of thumb, use \code{auto} only if: 92 | \begin{itemize} 93 | \item there is no other way to write the type (e.g. assigning a 94 | lambda to a variable), 95 | \item \underline{maybe} if the type is a well known idiom (e.g. \code{auto it = 96 | some\_container.begin()}, or for a loop variable in a range-based for 97 | loop over an associative container), but I would argue that writing 98 | the actual type would still be more explanatory for the reader. 99 | \end{itemize} 100 | 101 | Absolutely never use \code{auto} in place where you could have used 102 | basic types like \code{int} or \code{bool}, or by laziness. It is not 103 | because it is shorter that it improves the readability. On the 104 | contrary, the readability is improved by being clear about what is 105 | going on. 106 | \end{guideline} 107 | -------------------------------------------------------------------------------- /parts/11/bind.tex: -------------------------------------------------------------------------------- 1 | \subsection{Argument Bindings} 2 | 3 | \problemtitle 4 | 5 | The bindings example from \ref{sec:tuple} was quite complex, and it 6 | does not even handle member functions. Since it is already using 7 | \cpp11 features, it is left to the reader to consider how to implement 8 | something equivalent with pre-\cpp11 features. 9 | 10 | \solutiontitle 11 | 12 | \marginheader{}% 13 | % 14 | However, a better implementation of a binding is available in \cpp11, 15 | via \code{std::bind()}. This function creates a function object, of an 16 | unspecified type, that will forward its arguments to the bound 17 | function. This is something I would typically use in event handling. 18 | 19 | \begin{lstlisting} 20 | struct message_queue { /* … */ }; 21 | 22 | struct message_counter 23 | { 24 | void count_message(); 25 | }; 26 | 27 | void connect_handlers(message_queue& queue) 28 | { 29 | message_counter counter; 30 | 31 | // Here std::bind() creates a function object that calls 32 | // counter.process_message() when invoked. 33 | // 34 | // Note that the arguments of the function object are deduced from 35 | // the signature of message_dispatcher::count_message. 36 | queue.on_message(@\emcode{std::bind}@(&message_counter::process_message, &counter)); 37 | } 38 | \end{lstlisting} 39 | 40 | Interestingly, it is also possible to either force the value of an 41 | argument, or to redirect an argument from the caller to a specific 42 | argument of the called. 43 | 44 | \begin{lstlisting} 45 | struct message_queue { /* … */ }; 46 | 47 | void log_error(int queue_id, error e); 48 | 49 | void connect_error_handler(message_queue& queue, int queue_id) 50 | { 51 | // This one creates a function object accepting a single argument, 52 | // that calls log_error(queue_id, e), for a given argument e. 53 | // 54 | // Note that we must explicitly tell what to do with the argument 55 | // given by the caller here, via the placeholder. 56 | queue.on_message(@\emcode{std::bind}@(&log_error, queue_id, std::placeholders::_1)); 57 | } 58 | \end{lstlisting} 59 | 60 | In the above code, \code{std::placeholders::\_1} tells 61 | \code{std::bind} to pass whatever is received as the first argument 62 | (because the \_1) to the second argument of \code{log\_error} (second 63 | because it is the second following the function when the binding is 64 | created). 65 | 66 | Note that the standard does not define how many placeholders must be 67 | defined. 68 | -------------------------------------------------------------------------------- /parts/11/constexpr.tex: -------------------------------------------------------------------------------- 1 | \subsection{\code{constexpr}} 2 | \label{sec:constexpr} 3 | 4 | \problemtitle 5 | 6 | Let's say we have some complex computation, like for example counting 7 | the number of bits set to one in an integer: 8 | 9 | \begin{lstlisting} 10 | int popcount(unsigned n) 11 | { 12 | return (n == 0) ? 0 : ((n & 1) + popcount(n >> 1)); 13 | } 14 | \end{lstlisting} 15 | 16 | What happens when we want to be able to call this function both with 17 | run-time values and compile-time constant as arguments? In the code 18 | below we would want the size of the array to be a constant, but as it 19 | is written its size will be computed at run-time, which makes it a non 20 | constant-sized array, which is not standard compliant. 21 | 22 | \begin{lstlisting} 23 | int main(int argc, char**) 24 | { 25 | int array[popcount(45)]; 26 | printf("%d\n", popcount(argc)); 27 | 28 | return 0; 29 | } 30 | \end{lstlisting} 31 | 32 | A typical solution for this problem is to implement the computation 33 | via template classes and meta-programming: 34 | 35 | \lstinputlistinghl{28}{examples/constexpr/constexpr-98.cpp} 36 | 37 | This implementation works but has two major problems: first it is 38 | incredibly verbose, second it forces us to implement the same 39 | algorithm twice, respectively for run time and compile time 40 | computations, doubling the risk of bugs and errors. 41 | 42 | \solutiontitle 43 | 44 | The \code{constexpr} keyword introduced in \cpp11 allows us to use the 45 | same implementation for both compile-time and run-time computations. 46 | 47 | \lstinputlistinghl[emph=constexpr]{10}{examples/constexpr/constexpr-11.cpp} 48 | 49 | This keyword can be applied to a variable or a function to explicitly 50 | tell the compiler that it can and should be computed at compile-time 51 | when it appears in constant expressions. It is for example totally 52 | possible to call the \code{constexpr popcount()} function as a 53 | template argument, like in \code{popcount{}>()}. 54 | -------------------------------------------------------------------------------- /parts/11/decltype.tex: -------------------------------------------------------------------------------- 1 | \subsection{Type Deduction with \code{decltype}} 2 | \label{decltype} 3 | 4 | \problemtitle 5 | 6 | During the pre-\cpp11 era every variable, member, argument, etc. has 7 | to be explicitly typed. For example, if we were writing a template 8 | function operating on a range, how could we declare a variable of the 9 | type of its items? 10 | 11 | \begin{lstlisting} 12 | template 13 | < 14 | typename InputIt, 15 | typename OutputIt, 16 | typename Predicate, 17 | typename Transform, 18 | > 19 | void transform_if 20 | (InputIt first, InputIt last, OutputIt out, 21 | Predicate& predicate, Transform& transform) 22 | { 23 | for (; first != last; ++first) 24 | { 25 | /* some_type */ v = *first; 26 | if (predicate(v)) 27 | { 28 | *out = transform(v); 29 | ++out; 30 | } 31 | } 32 | } 33 | \end{lstlisting} 34 | 35 | \solutiontitle 36 | Getting the correct type to put in place of \code{some\_type} was not 37 | obvious, and required a fair share of template metaprogramming. Now, 38 | with the \code{decltype} specifier introduced in \cpp11, the 39 | programmer can tell the compiler to use ``the type of this 40 | expression''. 41 | 42 | 43 | \begin{lstlisting} 44 | template 45 | < 46 | typename InputIt, 47 | typename OutputIt, 48 | typename Predicate, 49 | typename Transform, 50 | > 51 | void transform_if 52 | (InputIt first, InputIt last, OutputIt out, 53 | Predicate& predicate, Transform& transform) 54 | { 55 | for (; first != last; ++first) 56 | { 57 | @\emcode{decltype(*first)}@& v = *first; 58 | if (predicate(v)) 59 | { 60 | *out = transform(v); 61 | ++out; 62 | } 63 | } 64 | } 65 | \end{lstlisting} 66 | 67 | In the example above, \code{decltype(*first)} is the type of the 68 | result of dereferencing \code{first}. 69 | -------------------------------------------------------------------------------- /parts/11/defaulted-constructors.tex: -------------------------------------------------------------------------------- 1 | %------------------------------------------------------------------------------- 2 | \subsection{Defaulted Constructors} 3 | 4 | \problemtitle 5 | 6 | Let's continue with constructors. Before \cpp11, each class would have 7 | implicit constructors unless stated otherwise. One example of a 8 | situation where an implicit constructor would not have been created 9 | was the explicit declaration of a custom constructor by the 10 | programmer. For example: 11 | 12 | \begin{lstlisting} 13 | struct foo 14 | { 15 | foo(int) {} 16 | }; 17 | 18 | int main() 19 | { 20 | foo f1; // fail 21 | foo f2(24); // ok 22 | foo f3(f2); // ok 23 | 24 | return 0; 25 | } 26 | \end{lstlisting} 27 | 28 | In the above example, \code{foo} has no default constructor (but has 29 | an implicit copy constructor). In order to have the default 30 | constructor, the programmer had to implement one. The main problem 31 | becomes maintenance: when new fields are added in the class, we have 32 | to remember to update the constructor to initialize them. 33 | 34 | \solutiontitle 35 | 36 | Starting with \cpp11, the programmer can tell the compiler to 37 | implement the constructor with what would have been the default 38 | implementation if it was not deleted. 39 | 40 | \begin{lstlisting} 41 | struct foo 42 | { 43 | foo()@\emcode{ = default}@; 44 | foo(int) {} 45 | }; 46 | 47 | int main() 48 | { 49 | foo f1; @\emcode{// ok}@ 50 | foo f2(24); // ok 51 | foo f3(f2); // ok 52 | 53 | return 0; 54 | } 55 | \end{lstlisting} 56 | -------------------------------------------------------------------------------- /parts/11/delegated-constructors.tex: -------------------------------------------------------------------------------- 1 | %------------------------------------------------------------------------------- 2 | \subsection{Delegated Constructors} 3 | 4 | \problemtitle 5 | 6 | Before \cpp11, constructors could not call other 7 | constructors. Consider the example below: 8 | 9 | \begin{lstlisting} 10 | struct foo 11 | { 12 | foo(bar* b, float f, int i) 13 | : m_bar(b), 14 | m_f(f), 15 | m_i(i) 16 | {} 17 | 18 | foo(bar* b, int i) 19 | // can't I call foo(b, 0, i) directly? 20 | : m_bar(b), 21 | m_f(0), 22 | m_i(i) 23 | {} 24 | 25 | private: 26 | bar* const m_bar; 27 | const float m_f 28 | const int m_i; 29 | }; 30 | \end{lstlisting} 31 | 32 | If we want to share initialization code between multiple constructors, 33 | then we have to put it in some separate member function called by the 34 | constructor, like this: 35 | 36 | \begin{lstlisting} 37 | struct foo 38 | { 39 | foo(bar* b, float f, int i) 40 | { 41 | @\emcode{init}@(b, f, i); 42 | } 43 | 44 | foo(bar* b, int i) 45 | { 46 | @\emcode{init}@(b, 0, i); 47 | } 48 | 49 | private: 50 | void @\emcode{init}@(bar* b, float f, int i) 51 | { 52 | m_bar = b; 53 | m_f = f; 54 | m_i = i; 55 | } 56 | 57 | // We cannot make any of these members const anymore. 58 | bar* m_bar; 59 | float m_f; 60 | int m_i; 61 | }; 62 | \end{lstlisting} 63 | 64 | This approach was kind of error-prone. Stuff may happen before and 65 | after the call to the \code{init()} function, and actually nothing 66 | prevents it to be called at any point in the life of the 67 | instance. Finally, this is incompatible with \code{const} members. 68 | 69 | \solutiontitle 70 | 71 | Starting from \cpp11, a constructor can call another constructor: 72 | 73 | \begin{lstlisting} 74 | struct foo 75 | { 76 | foo(bar* b, float f, int i) 77 | : m_bar(b), 78 | m_f(f), 79 | m_i(i) 80 | {} 81 | 82 | foo(bar* b, int i) 83 | : @\emcode{foo}@(b, 0, i) 84 | {} 85 | 86 | private: 87 | bar* const m_bar; 88 | float m_f; 89 | int m_i; 90 | }; 91 | \end{lstlisting} 92 | 93 | This solves all problems. 94 | -------------------------------------------------------------------------------- /parts/11/deleted-constructors.tex: -------------------------------------------------------------------------------- 1 | %------------------------------------------------------------------------------- 2 | \subsection{Deleted Constructors} 3 | 4 | \problemtitle 5 | 6 | Delegating constructors is a nice feature, but wat about totally 7 | removing a constructor? 8 | 9 | Consider the class below: 10 | 11 | \begin{lstlisting} 12 | struct scoped_listener 13 | { 14 | scoped_listener(dispatcher& d, callback c) 15 | : m_dispatcher(&d) 16 | { 17 | m_id = m_dispatcher->connect(c); 18 | } 19 | 20 | ~scoped_listener() 21 | { 22 | m_dispatcher->disconnect(m_id) 23 | } 24 | 25 | private: 26 | dispatcher* m_dispatcher; 27 | int m_id; 28 | }; 29 | \end{lstlisting} 30 | 31 | Creating copies of \code{scoped\_listener} does not make any sense, as 32 | all copies would share the same \code{m\_id} and will thus trigger the 33 | same call to \code{disconnect(int)} when destructed. See for example 34 | its usage below: 35 | 36 | \begin{lstlisting} 37 | void foo() 38 | { 39 | /* ... */ 40 | scoped_listener listener(d, c1); 41 | scoped_listener copy(listener); 42 | scoped_listener other(d, c2); 43 | 44 | { 45 | // This assignment does not call disconnect(c2). 46 | other = listener; 47 | // disconnect(c1) is called here, 48 | // when other goes out of scope. 49 | } 50 | // disconnect(c1) is called twice here: in the 51 | // destruction of listener and copy. 52 | } 53 | \end{lstlisting} 54 | 55 | One would typically want to forbid copies of \code{scoped\_listener} by 56 | disabling its copy constructor. 57 | 58 | Before \cpp11, one solution we would find here and there was to 59 | declare the copy constructor and assignment operator as private. The 60 | problem was that it was still available for the class and its 61 | friends. So the programmer would then either implement an always 62 | failing body for this constructor, emitting an error at run time, or 63 | would just not implement the constructor, thus triggering an error at 64 | link time. 65 | 66 | These solutions were kind of weak, in the sense that the error, if 67 | any, was presented quite late for the programmer, and with a not 68 | obvious explanation. 69 | 70 | \solutiontitle 71 | 72 | Now, starting with \cpp11, the constructor and operators can be 73 | explicitly deleted: 74 | 75 | \begin{lstlisting} 76 | struct scoped_listener 77 | { 78 | scoped_listener(const scoped_listener&)@\emcode{ = delete}@; 79 | scoped_listener& operator=(const scoped_listener&)@\emcode{ = delete}@; 80 | 81 | scoped_listener(dispatcher& d, callback c) 82 | : m_dispatcher(&d) 83 | { 84 | m_id = m_dispatcher->connect(c); 85 | } 86 | 87 | ~scoped_listener() 88 | { 89 | m_dispatcher->disconnect(m_id) 90 | } 91 | 92 | private: 93 | dispatcher* m_dispatcher; 94 | int m_id; 95 | }; 96 | \end{lstlisting} 97 | 98 | Using a deleted function will trigger a clear error from the compiler 99 | when the call is encountered. 100 | -------------------------------------------------------------------------------- /parts/11/extern-template.tex: -------------------------------------------------------------------------------- 1 | \subsection{External Templates} 2 | 3 | \problemtitle 4 | 5 | External templates are one of my favorite features from \cpp11. 6 | 7 | When we were writing template code before \cpp11, for example a 8 | template function, then every time the code was included in a 9 | compilation unit the compiler would instantiate all used 10 | symbols. Check for example the header below: 11 | 12 | \lstinputlisting{% 13 | examples/extern-template/factorial-98.hpp% 14 | } 15 | 16 | If this header was included in two .cpp files, and its function 17 | actually called, then its compiled code would be present in the object 18 | file of each .cpp; something we can check with \code{nm}. 19 | 20 | Following the example, let's compile the two files below: 21 | 22 | \lstinputlisting{% 23 | examples/extern-template/foo-98.cpp% 24 | } 25 | 26 | \lstinputlisting{% 27 | examples/extern-template/bar-98.cpp% 28 | } 29 | 30 | Then \code{nm} would print: 31 | 32 | \begin{lstlisting}[language=bash] 33 | $ nm bar-98.cpp.o foo-98.cpp.o 34 | 35 | bar-98.cpp.o: 36 | 000000000000001b T foo(int) 37 | @\emcode{0000000000000036 W int factorial(int)}@ 38 | 39 | foo-98.cpp.o: 40 | 000000000000001b T bar(int) 41 | @\emcode{0000000000000036 W int factorial(int)}@ 42 | \end{lstlisting} 43 | 44 | Not only does this consume space (54 bytes per file here) but it also 45 | costs a lot of work for the compiler and the linker. All of this adds 46 | up, even for medium projects. Imagine that for each template function 47 | or class the compiler parses the code, then it compiles it, then 48 | writes all these bytes on disk; then all these bytes are read again by 49 | the linker, who sorts all these duplicate symbols to keep only one. 50 | 51 | At the end of this process, literally all the work done by the 52 | compiler has been useless. Wouldn't it have been better not to do it 53 | in the first place? The linker then spent more time removing the crap 54 | rather than actually linking, and the programmer was wondering if he 55 | could get a more powerful computer. Again. 56 | 57 | \solutiontitle 58 | 59 | Thankfully the \code{extern template} from \cpp11 allows us to skip 60 | all this useless work. First we have to tell the compiler not to 61 | instantiate the template for a subset of valid types by adding a 62 | single line to our header: 63 | 64 | \lstinputlistinghl{15}{% 65 | examples/extern-template/factorial-11.hpp% 66 | } 67 | 68 | This line tells the compiler not to instantiate 69 | \code{factorial()} when \code{T = int}. Then we add a .cpp file 70 | where we explicitly ask for the instantiation: 71 | 72 | \lstinputlisting{% 73 | examples/extern-template/factorial-11.cpp% 74 | } 75 | 76 | That's it. Let's check with \code{nm}: 77 | 78 | \begin{lstlisting}[language=bash] 79 | $ nm bar-11.cpp.o foo-11.cpp.o factorial.cpp 80 | 81 | bar-11.cpp.o: 82 | 000000000000001b T bar(int) 83 | 84 | foo-11.cpp.o: 85 | 000000000000001b T foo(int) 86 | 87 | factorial-11.cpp.o: 88 | 0000000000000036 W int factorial(int) 89 | \end{lstlisting} 90 | 91 | The template function is indeed compiled in a single file, and absent 92 | from the others\footnote{We can push even further in this case, by 93 | having the whole body of \code{factorial()} in the .cpp file and only 94 | its signature in the header. It would not only avoid the parsing of 95 | the code but, more importantly, allow to remove from the header all 96 | include directives related to implementation details. Note that in 97 | this case the extern keyword can even be omitted.}. 98 | 99 | \begin{guideline} 100 | If you are writing template code for which you know some or all 101 | instantiations, then add an \code{extern template} line for them in 102 | the header, and explicitly instantiate them in an implementation file. 103 | This is not always feasible, but when it can be done it should be done 104 | \end{guideline} 105 | -------------------------------------------------------------------------------- /parts/11/free-begin.tex: -------------------------------------------------------------------------------- 1 | \subsection{Beginning and End of Sequence} 2 | 3 | \problemtitle 4 | 5 | All containers from the STL have a \code{begin()} and \code{end()} 6 | member function to get an iterator on the first element in the 7 | sequence or, respectively, just after the last element. Unfortunately, 8 | there is no such function for the most basic sequences, i.e. C-like 9 | arrays, so code like that was sure to fail before \cpp11: 10 | 11 | \begin{lstlisting} 12 | template 13 | void replace_existing 14 | (Sequence& s, const T& old_value, const T& new_value) 15 | { 16 | *std::find(s.begin(), s.end(), old_value) = new_value; 17 | } 18 | 19 | void foo() 20 | { 21 | int a[] = { 1, 4, 3 }; 22 | replace_existing(a, 4, 2); 23 | } 24 | \end{lstlisting} 25 | 26 | \solutiontitle 27 | 28 | \marginheader{\cppheader{iterator}}% 29 | % 30 | Fortunately, \cpp11 introduces the 31 | \code{std::begin()} and \code{std::end()} free functions which accepts 32 | a C-like array\footnote{as long as we include \cppheader{array}}. Now, 33 | this code will work in all cases: 34 | 35 | \begin{lstlisting} 36 | template 37 | void replace_existing 38 | (Sequence& s, const T& old_value, const T& new_value) 39 | { 40 | *std::find(@\emcode{std::begin(s)}@, @\emcode{std::end(s)}@, old_value) = new_value; 41 | } 42 | 43 | void foo() 44 | { 45 | int a[] = { 1, 4, 3 }; 46 | replace_existing(a, 4, 2); 47 | } 48 | \end{lstlisting} 49 | -------------------------------------------------------------------------------- /parts/11/function.tex: -------------------------------------------------------------------------------- 1 | \subsection{Functions} 2 | 3 | \problemtitle 4 | 5 | Storing functions in a variable in \cpp{} used to be a pain. For 6 | example, how would we implement \code{callable} such that the code 7 | below works? 8 | 9 | \begin{lstlisting} 10 | void foo(); 11 | void bar(int arg); 12 | 13 | struct some_object 14 | { 15 | void some_method(); 16 | }; 17 | 18 | void test(); 19 | { 20 | std::vector scheduled; 21 | 22 | scheduled.push_back(&foo); 23 | // bar with arg = 5. 24 | scheduled.push_back(std::bind(&bar, 5)); 25 | 26 | some_object c; 27 | scheduled.push_back(std::bind(&some_object::some_method, &c)); 28 | 29 | // All stored functions can be called as if they were void(). 30 | scheduled[0](); 31 | scheduled[1](); 32 | scheduled[2](); 33 | } 34 | \end{lstlisting} 35 | 36 | Having a working type for all these use cases is a huge task, and 37 | before \cpp11 our only hope were Boost.Function, some other 38 | libraries\footnote{Search for FastDelegate, the Impossibly Fast C++ 39 | Delegates, More Fasterest Delegates, and Ultimate Fast C++ Delegates 40 | II'. Some of them may not exist.}, or and homemade solution. 41 | 42 | A binding like presented in Section~\ref{sec:tuple} is a partial 43 | answer to that but first, it does not even handle member functions, 44 | and two, it is already \cpp11. 45 | 46 | \solutiontitle 47 | 48 | \marginheader{}% 49 | % 50 | The \code{std::function} type introduced in \cpp11, in combination 51 | with \code{std::bind} \aref{bind}, is exactly what we 52 | need to fix our previous example. The former is an object that represents a 53 | function, and that can be called to invoke this function. It can be a 54 | function object or a free function, everything works. 55 | 56 | \begin{lstlisting} 57 | void foo(); 58 | void bar(int arg); 59 | 60 | struct some_object 61 | { 62 | void some_method(); 63 | }; 64 | 65 | void test(); 66 | { 67 | std::vector<@\emcode{std::function}@> scheduled; 68 | 69 | scheduled.push_back(&foo); 70 | // bar with arg = 5. 71 | scheduled.push_back(std::bind(&bar, 5)); 72 | 73 | some_object c; 74 | scheduled.push_back(std::bind(&some_object::some_method, &c)); 75 | 76 | // All stored functions can be called as if they were void(). 77 | scheduled[0](); 78 | scheduled[1](); 79 | scheduled[2](); 80 | } 81 | \end{lstlisting} 82 | 83 | As far as can tell there is only one downside to \code{std::function}, 84 | it is that every call begins with a test checking if a function is 85 | set. If we care about performance, it can be an issue\footnote{This 86 | test is used to throw an \code{std::bad\_function\_call} if the 87 | invocation is done on an empty instance. If you wonder why 88 | \code{std::function} does not reference by default a function that 89 | throws the exception, such that no test is done and the exception is 90 | still thrown when an empty function is invoked, know that I wonder 91 | too. If you have insight about it, I would love to know.}. 92 | -------------------------------------------------------------------------------- /parts/11/hash-table.tex: -------------------------------------------------------------------------------- 1 | \subsection{Hash Tables} 2 | 3 | \problemtitle 4 | 5 | There were two main associative containers in \cpp{} before \cpp11: 6 | \code{std::vector} and the likes, to associate integer keys with 7 | almost any value type, and \code{std::map}, to use any key type whose 8 | values can be strictly ordered. Similar to the latter, \code{std::set} 9 | is an ordered set of values. In practice, \code{std::map} is an 10 | \code{std::set} where the value type is \code{std::pair}, with the key 11 | as the first field (with a const modifier), and the value as the 12 | second field. 13 | 14 | These last two collections had several problems, the main one being 15 | that they require a total order on their entries. However, it is not 16 | exceptional to have a type for which \code{operator<()} is not defined 17 | and where providing one would be weird. 18 | 19 | \begin{lstlisting} 20 | struct color 21 | { 22 | uint8_t red; 23 | uint8_t green; 24 | uint8_t blue; 25 | 26 | // Does it make sense to say that a color is less than another color? 27 | bool operator<(const color& that) const 28 | { 29 | // Note that in @\cpp@11 we could have used std::tie() to create a 30 | // tuple from the fields @\aref{sec:tuple}@, then used 31 | // std::tuple::operator<() to compare them lexicographically. 32 | 33 | if (red != that.red) 34 | return red < that.red; 35 | 36 | if (green != that.green) 37 | return green < that.green; 38 | 39 | return blue < that.blue; 40 | } 41 | }; 42 | \end{lstlisting} 43 | 44 | A way to avoid the weird operator is to declare the comparison 45 | operator outside the type, as an independent function object. It has 46 | the effect of not pretending that there is a meaningful order on the 47 | given type. The type of the function object is then passed to 48 | \code{std::set} or \code{std::map}; it becomes a property of the 49 | container (i.e. the way its entries are ordered) instead of a property 50 | of the data. 51 | 52 | \begin{lstlisting} 53 | struct color 54 | { 55 | uint8_t red; 56 | uint8_t green; 57 | uint8_t blue; 58 | }; 59 | 60 | // This is one way to order, amongst many. The advantage here is that 61 | // there is no inherent ordering attached to color. 62 | struct color_lexicographical_order 63 | { 64 | bool operator()(const color& left, const color& right) const 65 | { 66 | if (left.red != right.red) 67 | return left.red < right.red; 68 | 69 | if (left.green != right.green) 70 | return left.green < right.green; 71 | 72 | return left.blue < right.blue; 73 | } 74 | }; 75 | 76 | std::set used_colors; 77 | \end{lstlisting} 78 | 79 | Another problem with \code{std::set} and \code{std::map} is that they 80 | are implemented as a balanced tree, typically a red-black tree, where 81 | the nodes are dynamically allocated. This is not very 82 | performance-friendly since the data ends up scattered in memory, with 83 | an additional cost of three pointers per entry. Additionally, look-up 84 | is logarithmic. 85 | 86 | \solutiontitle 87 | 88 | \marginheader{,\\ 89 | }% 90 | % 91 | Since \cpp11, these containers are advantageously replaced by 92 | \code{std::unordered\_set} and \code{std::unordered\_map}, which 93 | provide the same service but with an implementation based on hash 94 | tables. Now, look-up is more often constant-time than anything 95 | else. The difficulty being to find a good hash function for the stored 96 | type. 97 | 98 | \begin{lstlisting} 99 | struct color 100 | { 101 | // Both std::unordered_set and std::unordered_map need a way to tell 102 | // if two instances are equal, in case of a hash collision. 103 | bool operator==(const color& that) const 104 | 105 | uint8_t red; 106 | uint8_t green; 107 | uint8_t blue; 108 | }; 109 | 110 | namespace std 111 | { 112 | // We can specialize std::hash for our own types. It is one of the 113 | // few symbols from the STL that we are allowed to specialize. 114 | template<> 115 | struct hash 116 | { 117 | std::size_t operator()(const color& c) const 118 | { 119 | return 120 | ((std::size_t)c.red << 16) 121 | | ((std::size_t)c.green << 8) 122 | | (std::size_t)c.blue; 123 | } 124 | }; 125 | } 126 | 127 | // No need to define the hash since we defined it via 128 | // std::hash. Alternatively, we could have set the second template 129 | // parameter std::unordered_set. 130 | std::unordered_set used_colors; 131 | \end{lstlisting} 132 | 133 | Moreover, a new way to insert elements in a set or a map has been 134 | introduced, via the \code{emplace()} method. This method will create 135 | the item in-place, without copies, while the previous \code{insert()} 136 | approach would copy its argument into the container. It is available 137 | both for the ordered and unordered variants: 138 | 139 | \begin{lstlisting} 140 | struct color 141 | { 142 | color(uint8_t r, uint8_t g, uint8_t b); 143 | 144 | bool operator==(const color& that) const 145 | 146 | uint8_t red; 147 | uint8_t green; 148 | uint8_t blue; 149 | }; 150 | 151 | std::unordered_set used_colors; 152 | 153 | // The arguments are forwarded to the constructor of color. 154 | used_colors.emplace(218, 13, 13); 155 | \end{lstlisting} 156 | 157 | For the map version, since the entries are instances of 158 | \code{std::pair}, we cannot pass all parameters in a single argument 159 | list, as the compiler would not know where the constructor arguments 160 | for \code{std::pair::first} would end and where the ones for 161 | \code{std::pair::second} would start. Consequently, we must use tuples 162 | \aref{sec::tuple} and the piecewise constructor: 163 | 164 | \begin{lstlisting} 165 | std::unordered_map color_count; 166 | 167 | // The std::piecewise_construct is here to select the corresponding 168 | // constructor from std::pair. The triplet argument will be forwarded 169 | // directly to the construction of the first member; The second 170 | // singleton argument will be forwarded to the second member. 171 | color_count.emplace 172 | (std::piecewise_construct, 173 | std::forward_as_tuple(218, 13, 13), 174 | std::forward_as_tuple(1)); 175 | \end{lstlisting} 176 | 177 | The main problem with \code{std::unordered\_set} and 178 | \code{std::unordered\_map} is that they perform quite 179 | poorly. Unfortunately, due to the constraints imposed by the standard, 180 | they cannot be implemented in another way. 181 | 182 | \begin{guideline} 183 | If you need an hash table in the internals of your application or 184 | library, i.e. it won't be visible by anything outside, then you 185 | probably want to switch to another implementation. Otherwise, if your 186 | library or application exposes a hash table, you have to consider: 187 | 188 | \begin{enumerate} 189 | \item if it makes sense to pass the exposed table as-is to another 190 | third-party application, then use the standard containers, 191 | \item if the exposed table is expected not to go anywhere, then use a 192 | better container. 193 | \end{enumerate} 194 | 195 | So far, I have been quite satisfied with the robin hood hashing from 196 | Martin Ankerl, a.k.a martinus, at 197 | \url{https://github.com/martinus/robin-hood-hashing}. 198 | \end{guideline} 199 | -------------------------------------------------------------------------------- /parts/11/initializer-list.tex: -------------------------------------------------------------------------------- 1 | \subsection{Initializer list} 2 | \label{initializer-list} 3 | 4 | \problemtitle 5 | 6 | Initializing a container like \code{std::vector} with a predefined 7 | sequence of values was quite verbose before \cpp11, as we had to 8 | insert the values one by one: 9 | 10 | \begin{lstlisting} 11 | void transform 12 | (std::vector& values, const std::vector& multipliers); 13 | 14 | void up_down_transform(std::vector& values) 15 | { 16 | // Pfff it is not even const. 17 | std::vector pattern(4); 18 | pattern[0] = 0; 19 | pattern[1] = 1; 20 | pattern[2] = 0; 21 | pattern[3] = -1; 22 | 23 | // Can't we have simple initialization, like we have for arrays? 24 | // const int pattern[4] = {0, 1, 0, -1}; 25 | 26 | transform(values, pattern); 27 | } 28 | \end{lstlisting} 29 | 30 | \solutiontitle 31 | 32 | \marginheader{}% 33 | % 34 | However, thanks to the the introduction of 35 | \code{std::initializer\_list} in \cpp11, we can now initialize our 36 | containers wich bracket enclosed values: 37 | 38 | \begin{lstlisting} 39 | void transform 40 | (std::vector& values, const std::vector& multipliers); 41 | 42 | void up_down_transform(std::vector& values) 43 | { 44 | const std::vector pattern = {0, 1, 0, -1}; 45 | transform(values, pattern); 46 | 47 | // This one also works: 48 | // transform(values, {0, 1, 0, -1}); 49 | } 50 | \end{lstlisting} 51 | 52 | It's just like uniform initialization \aref{uniform-initialization}! 53 | Or is it? 54 | 55 | \subsubsection{The Problem with \code{std::initializer\_list}} 56 | 57 | Instances of \code{std::initializer\_list} are created by the compiler 58 | when it encounters a list of values between brackets and if the target 59 | to which these values are assigned is, or can be constructed from, an 60 | \code{std::initializer\_list}. 61 | 62 | In the example above, we can create a vector from the values because 63 | \code{std::vector} defines a constructor taking an 64 | \code{std::initializer\_list} as it sole argument. This constructor 65 | then copies the values from the list into the vector\footnote{Check 66 | \cite{beware-of-copies-initializer-list} for an illustration of the 67 | problem.}. 68 | 69 | \bigskip 70 | 71 | I think it is important to emphasize that: the constructor 72 | \emph{copies} the values from the list. There is no way it can move 73 | them, let alone wrap them. 74 | 75 | \bigskip 76 | 77 | So we have something that looks surreptitiously like the good old 78 | simple and efficient aggregate initialization, that is consequently 79 | identical in its syntax to uniform initialization 80 | \aref{uniform-initialization}, and that is actually a quite 81 | inefficient way to initialize something as soon as the element type is 82 | non trivial. 83 | 84 | The worse part is that bracket initialization is pushed by the 85 | so-called ``modern'' \cpp{} trend, propagating this inefficiency 86 | everywhere. 87 | 88 | \begin{guideline} 89 | Avoid \code{std::initializer\_list}. 90 | 91 | If you really, really, want the target container to be const, then 92 | use an immediately invoked lambda to construct it: 93 | 94 | \begin{lstlisting} 95 | const std::vector pattern = 96 | []() -> std::vector 97 | { 98 | std::vector result(4); 99 | result[0] = 0; 100 | result[1] = 1; 101 | result[2] = 0; 102 | result[3] = -1; 103 | 104 | return result; 105 | }(); // Watch out for the parentheses here, 106 | // it is a call to the lambda. 107 | \end{lstlisting} 108 | \end{guideline} 109 | 110 | -------------------------------------------------------------------------------- /parts/11/lambdas.tex: -------------------------------------------------------------------------------- 1 | \subsection{Lambdas} 2 | \label{sec:lambda} 3 | 4 | \problemtitle 5 | 6 | How would we pass a custom comparator to \code{std::max\_element} 7 | before \cpp11, say to compare strings by increasing size? Certainly by 8 | writing a free or static function taking two strings as arguments and 9 | returning the result of the comparison. 10 | 11 | \begin{lstlisting} 12 | // Comparator for strings by increasing size. 13 | // Declared as a free function. 14 | static bool string_size_less_equal 15 | (const std::string& lhs, const std::string& rhs) 16 | { 17 | return lhs.size() < rhs.size(); 18 | } 19 | 20 | std::size_t 21 | largest_string_size(const std::vector& strings) 22 | { 23 | // The comparator is outside the scope of this function. 24 | return 25 | std::max_element 26 | (strings.begin(), strings.end(), &string_size_less_equal) 27 | ->size(); 28 | } 29 | \end{lstlisting} 30 | 31 | Now what if we needed a parameterized comparator, for example to call 32 | \code{std::find\_if} to search for a string of a specific size? The 33 | free function would not allow to store the size, so we would 34 | certainly write a functor object, i.e. a \code{struct} storing the 35 | size parameter and defining an \code{operator()} receiving a string 36 | and returning the result of the comparison. 37 | 38 | \begin{lstlisting} 39 | // Need a function object if the comparator has parameters. 40 | struct string_size_equals 41 | { 42 | std::size_t size; 43 | 44 | bool operator()(const std::string& string) const 45 | { 46 | return string.size() == size; 47 | } 48 | }; 49 | 50 | bool has_string_of_size 51 | (const std::vector& strings, std::size_t s) 52 | { 53 | string_size_equals comparator = {s}; 54 | 55 | return 56 | std::find_if(strings.begin(), strings.end(), comparator) 57 | != strings.end(); 58 | } 59 | \end{lstlisting} 60 | 61 | \solutiontitle 62 | 63 | Having the comparators as independent objects or functions is nice if 64 | they are used in many places, but for a single use it is undoubtedly 65 | too verbose. And confusing too. Wouldn't it be clearer if the 66 | single-use comparator was declared next to where it is used? 67 | Thankfully this is something we can do with lambdas, starting with 68 | \cpp11: 69 | 70 | \begin{lstlisting} 71 | bool has_string_of_size 72 | (const std::vector& strings, std::size_t s) 73 | { 74 | // Only three lines for the equivalent of the type 75 | // declaration, definition and the instantiation. 76 | // The third argument is a lambda. 77 | return std::find_if 78 | (strings.begin(), strings.end(), 79 | [=](const std::string& string) -> bool 80 | { 81 | return string.size() == s; 82 | }) 83 | != strings.end(); 84 | } 85 | \end{lstlisting} 86 | 87 | \begin{guideline} 88 | Mind the next reader: keep your lambdas small. 89 | \end{guideline} 90 | 91 | %------------------------------------------------------------------------------- 92 | \subsubsection{The Internals of Lambdas} 93 | \label{lambdas-internals} 94 | 95 | A declaration like 96 | 97 | \begin{lstlisting} 98 | [a, b, c]( /* arguments */ ) -> T { /* statements */ } 99 | \end{lstlisting} 100 | 101 | is equivalent to 102 | 103 | \begin{lstlisting} 104 | struct something 105 | { 106 | T operator()( /* arguments */ ) const { /* statements */ } 107 | 108 | /* deduced type */ a; 109 | /* deduced type */ b; 110 | /* deduced type */ c; 111 | }; 112 | \end{lstlisting} 113 | 114 | Actually the compiler will create a unique type like this struct for 115 | every lambda we write. 116 | 117 | More conceptually, the parts of a lambda are the following: 118 | 119 | \bigskip 120 | 121 | \begin{center} 122 | [{\it capture}]({\it arguments}) {\it specifier} -\textgreater 123 | {\it return\_type} \{ {\it body} \} 124 | \end{center} 125 | 126 | \bigskip 127 | 128 | Where: 129 | 130 | \begin{itemize} 131 | \item {\it capture} is a list of variables from the parent scope that 132 | must be accessible inside the lambda. Use \code{[=]} to tell the 133 | compiler to automatically copy any variable used by the lambda, or 134 | \code{[\&]} to keep a reference to the corresponding variables from 135 | the parent scope. Variables can also be captured in a fine-grained 136 | way, e.g. \code{[=a, \&b]} to copy the value of \code{a} but store a 137 | reference to \code{b}. 138 | \item {\it arguments} are the arguments of the function. 139 | \item By default the variables captured by value cannot be assigned to 140 | in the body, unless we put the mutable keyword in {\it 141 | specifier}. In effect, it removes the \code{const} from 142 | \code{operator()}. 143 | \item {\it return\_type} is the type of the value returned by this 144 | function, if any, or void otherwise. Contrary to any other 145 | function, the return type appear after the argument list instead of 146 | before. 147 | \item {\it body} is the body of the function. 148 | \end{itemize} 149 | 150 | -------------------------------------------------------------------------------- /parts/11/miscellaneous.tex: -------------------------------------------------------------------------------- 1 | In the previous sections we saw many nice features from \cpp11. There 2 | are actually many more! As I did not use all of them, here come a 3 | short description for the missing ones. 4 | 5 | \subsection{Regular Expressions} 6 | 7 | \marginheader{\cppheader{regex}}% 8 | % 9 | Regular expressions are now first class citizen in the STL. We can 10 | finally easily write an HTML parser in a few lines 11 | of \cpp{}\footnote{Reference for the 12 | joke: \url{https://stackoverflow.com/a/1732454/1171783}. If you don't 13 | follow this link, just know that one cannot correctly parse random 14 | HTML with a regular expression.}! 15 | 16 | Interestingly, the format for the expressions can be of almost any 17 | existing syntax: ECMAScript, grep, awk… 18 | 19 | \subsection{Explicit Conversion Operators} 20 | 21 | Conversion operators can now be declared as explicit, to avoid 22 | unexpected conversions: 23 | 24 | \begin{lstlisting} 25 | // This struct wraps an 8 bits non-negative integer value. 26 | struct custom_uint8 { /* … */ }; 27 | 28 | // This struct wraps a 64 bits signed integer value. 29 | struct custom_int64 { /* … */ }; 30 | 31 | // This struct wraps a 32 bits integer value. 32 | struct custom_int32 33 | { 34 | // This operator is explicit, as information may be lost when 35 | // truncating to 8 bits. Thus we don't want it to happen silently. 36 | @\emcode{explicit}@ operator custom_uint8() const 37 | { 38 | return custom_uint8(m_value); 39 | } 40 | 41 | // This operator is implicit, as all signed 32 bits values can be 42 | // represented in a signed 64 bits. 43 | operator custom_int64() const 44 | { 45 | return custom_int64(m_value); 46 | } 47 | 48 | private: 49 | int32_t m_value; 50 | }; 51 | 52 | void foo() 53 | { 54 | custom_uint8 i8; 55 | custom_int32 i32; 56 | custom_int64 i64; 57 | 58 | // This is ok thanks to the implicit conversion operator. 59 | i64 = i32; 60 | 61 | // This won't work since there is an implicit conversion. 62 | i8 = i32; 63 | 64 | // Here the conversion is explicit, so it will work. 65 | i8 = static_cast(i32); 66 | } 67 | \end{lstlisting} 68 | 69 | \subsection{Unrestricted Unions} 70 | 71 | Unions can now contain non-POD members. I do not know where it is 72 | useful but it can be done. 73 | 74 | \subsection{String Literals} 75 | 76 | New string literals have been introduced to represent UTF-8, UTF-16, 77 | UTF-32 strings, as well as raw strings: 78 | 79 | \begin{lstlisting} 80 | const char* utf_8 = @\emcode{u8}@"I'm UTF-8."; 81 | const char* utf_16 = @\emcode{u}@"I'm UTF-16."; 82 | const char* utf_32 = @\emcode{U}@"I'm UTF-32."; 83 | 84 | const char* raw = @\emcode{R"\_(}@This text is stored as is, 85 | line breaks included, 86 | spaces included. 87 | It is thus a four-lines text.@\emcode{)\_}@"; 88 | \end{lstlisting} 89 | 90 | %------------------------------------------------------------------------------- 91 | \subsection{User Defined Literals} 92 | 93 | Have you ever mixed some units like in the declartion of \code{m} below? 94 | 95 | \begin{lstlisting} 96 | struct mass 97 | { 98 | mass(float kg) 99 | : kilograms(kg) 100 | {} 101 | 102 | float kilograms; 103 | }; 104 | 105 | void foo() 106 | { 107 | // A mass of 2000 grams. 108 | mass m(2000); 109 | 110 | // Oops, mass() takes the value in kilograms :( 111 | } 112 | \end{lstlisting} 113 | 114 | If you have already made this mistake, or just if you use this kind of 115 | code, you may be happy to learn that you can now use custom suffixes 116 | for literals, which may help to explicit the unit. 117 | 118 | \begin{lstlisting} 119 | // We define the 'g' suffix for float numbers, to represent grams. 120 | mass @\emcode{operator"" \_g}@(float v) 121 | { 122 | return mass(v / 1000); 123 | } 124 | 125 | void foo() 126 | { 127 | // A mass of 2000 grams. 128 | mass m = 2000@\emcode{\_g}@; 129 | 130 | // m.kilograms is equal to 2, everything is fine. 131 | } 132 | \end{lstlisting} 133 | 134 | %------------------------------------------------------------------------------- 135 | \subsection{Very Long Integers} 136 | 137 | Sometimes an \code{int} is a bit short to store large values. Then we 138 | switch to \code{long int}, but sometimes it is still not enough. Now 139 | with \cpp11 we can also switch to \code{long long int}\footnote{Also 140 | available as \code{long int long}, or \code{int long long}, 141 | or \code{signed long int long}, or \code {long int signed long}, etc.}. 142 | 143 | This type is guaranteed to be made of at least 64 bits, 144 | while \code{int} and \code{long int} are made of at least 16 and 32 145 | bits respectively. 146 | 147 | Actually, I doubt I will ever use it, because when I need to store a 148 | value in at least $n$ bits, I usually choose \code{int$n$\_t} type 149 | from \cppheader{cstdint}. 150 | 151 | %------------------------------------------------------------------------------- 152 | \subsection{Size of Members} 153 | 154 | Computing the size of a struct member in the old days of \cpp{} 155 | required to use an instance of the struct, like in: 156 | 157 | \begin{lstlisting} 158 | struct foo 159 | { 160 | int m; 161 | }; 162 | 163 | int main() 164 | { 165 | // There is no way to apply sizeof directly to m, so we "create" 166 | // an instance just to get the member. Fortunately the expression 167 | // on which sizeof is applied is not evaluated. 168 | printf("%ld\n", sizeof(foo().m)); 169 | 170 | return 0; 171 | } 172 | \end{lstlisting} 173 | 174 | This is doable for simple structs but clearly becomes difficult if 175 | the constructor needs arguments. 176 | 177 | In \cpp11 there is now a syntax to get the size of a member: 178 | 179 | \begin{lstlisting} 180 | int main() 181 | { 182 | printf("%ld\n", sizeof(@\emcode{foo::m}@)); 183 | return 0; 184 | } 185 | \end{lstlisting} 186 | 187 | %------------------------------------------------------------------------------- 188 | \subsection{Type Alignment} 189 | 190 | If you are the kind of person who write allocators or who use 191 | placement new in a buffer, then you will be happy to learn 192 | about \code{alignas(T)}, which sets a type alignment to the 193 | value \code{T}, if it is an integer, or to match the alignment of the 194 | type \code{T} otherwise. Similarly, \code{alignof(T)} is the 195 | alignement of the type \code{T}. 196 | 197 | \begin{lstlisting} 198 | char buffer[1024]; 199 | int consumed = 0; 200 | 201 | template 202 | T* allocate() 203 | { 204 | const int shift = consumed % @\emcode{alignof(T)}@; 205 | const int offset = (shift == 0) ? 0 : (@\emcode{alignof(T)}@ - shift); 206 | 207 | T* const result = new (buffer + consumed + offset) T(); 208 | consumed += offset + sizeof(T); 209 | 210 | return result; 211 | } 212 | \end{lstlisting} 213 | 214 | %------------------------------------------------------------------------------- 215 | \subsection{Attributes} 216 | 217 | Maybe have you already seen the \code{\_\_attribute\_\_} token in 218 | some \cpp{} code? This is used to annotate the code with hints or 219 | directives about some code. Unfortunately it is a compiler extension, 220 | so it was not usable in portable code. 221 | 222 | Starting with \cpp11, we now have a standard way to specify attributes 223 | with the \code{[[some\_attribute]]} syntax. Their semantic is still 224 | implementation-defined but at least it is syntaxically portable. 225 | 226 | One of the only two well defined attributes in the \cpp11 227 | standard is \code{[[noreturn]]}, which tells that a function never 228 | returns to the caller: 229 | 230 | \begin{lstlisting} 231 | @\emcode{[[noreturn]]}@ void fatal_error(const char* m) 232 | { 233 | printf("%s\n", m); 234 | exit(1); 235 | } 236 | \end{lstlisting} 237 | 238 | The second one is \code{[[carries\_dependency]]} and I won't talk 239 | about it. 240 | -------------------------------------------------------------------------------- /parts/11/move.tex: -------------------------------------------------------------------------------- 1 | %------------------------------------------------------------------------------- 2 | \label{move} 3 | 4 | \problemtitle 5 | 6 | Copies! Copies everywhere! And dynamic allocations too! 7 | 8 | So was the world before \cpp11. In these old days, if we had to pass 9 | a large object to a function that needed its own instance of it, then 10 | we would have certainly created a copy of it. 11 | 12 | \begin{lstlisting} 13 | struct catalog 14 | { 15 | catalog(const std::vector& entries) 16 | // Here we have one allocaction, for the storage, 17 | // plus copies of the elements from the vector. 18 | : m_entries(entries) 19 | {} 20 | 21 | private: 22 | std::vector m_entries; 23 | }; 24 | 25 | void create_catalog(int n) 26 | { 27 | // One allocation of n items, plus their initialization. 28 | std::vector entries(n); 29 | 30 | // ... 31 | 32 | catalog c(entries); 33 | // I don't need the entries anymore, but they are still here. 34 | } 35 | \end{lstlisting} 36 | 37 | \solutiontitle 38 | 39 | \marginheader{}% 40 | % 41 | \Cpp11 introduces the move semantics and the \code{std::move()} 42 | function. In practice it means far fewer copies, as the instances' 43 | data is transfered from one place to another. 44 | 45 | \begin{lstlisting} 46 | struct catalog 47 | { 48 | // Note the pass-by-value for the argument. 49 | catalog(std::vector entries) 50 | // Explicit transfer into m_entries, no allocation. 51 | : m_entries(@\emcode{std::move}@(entries)) 52 | {} 53 | 54 | private: 55 | std::vector m_entries; 56 | }; 57 | 58 | void create_catalog(int n) 59 | { 60 | // The single allocation in this program. 61 | std::vector entries(n); 62 | 63 | // ... 64 | 65 | // I don't need the entries anymore, so I transfer them. 66 | catalog c(@\emcode{std::move}@(entries)); 67 | } 68 | \end{lstlisting} 69 | 70 | In the example above, there is only one allocation, for the vector of 71 | entries in \code{create\_catalog()}, and zero copies. The ownership of 72 | the allocated space is actually transfered from one vector to another 73 | every time \code{std::move()} is used, until it ends up 74 | in \code{m\_entries}. 75 | 76 | %------------------------------------------------------------------------------- 77 | \subsection{The Move Constructor and Assignment Operator} 78 | \label{sec:move-constructor} 79 | 80 | In order to make it work, a new type of reference was added to 81 | the language; and classes can use this reference in constructors and 82 | assignment operators to implement the actual transfer of data from one 83 | instance to another. So to mark an argument as moveable, use \&\&: 84 | 85 | \begin{lstlisting} 86 | struct foo 87 | { 88 | foo(foo@\emcode{\&\&}@ that) 89 | : m_resource(that.m_resource) 90 | { 91 | that.m_resource = nullptr; 92 | } 93 | 94 | foo& operator=(foo@\emcode{\&\&}@ that) 95 | { 96 | std::swap(m_resource, that.m_resource); 97 | } 98 | }; 99 | 100 | // All of these call the constructor defined above. 101 | foo f(foo()); 102 | foo f(construct_a_foo()); 103 | foo f(std::move(g)); 104 | 105 | // All of these call the assignment operator defined above. 106 | f = foo(); 107 | f = construct_a_foo(); 108 | f = std::move(g); 109 | \end{lstlisting} 110 | 111 | The parameter of such functions is considered a temporary on the call 112 | site. They are actually not restricted to constructors or assignment 113 | operators, and can be used in any function. 114 | 115 | The semantics of such arguments must be interpreted as ``I {\em may} 116 | steal your data''. The {\em may} is important here, as there is no 117 | guarantee on the call site that the instance going through an 118 | \code{std::move} is actually moved. 119 | 120 | %------------------------------------------------------------------------------- 121 | \subsection{\code{std::move}, the Subtleties} 122 | 123 | Naming quality: \faStar\faStarO\faStarO\faStarO\faStarO. Would have 124 | put zero stars if I could. 125 | 126 | As a great example of ``naming things is hard'', \code{std::move} does 127 | not move anything. It actually just marks the value as transferable, 128 | by casting it to an rvalue-reference. See this actual implementation 129 | exctracted from GCC 9: 130 | 131 | \begin{lstlisting} 132 | template 133 | constexpr typename std::remove_reference<_Tp>::type&& 134 | move(_Tp&& __t) noexcept 135 | { 136 | return static_cast 137 | < 138 | typename std::remove_reference<_Tp>::type&& 139 | >(__t); 140 | } 141 | \end{lstlisting} 142 | 143 | \begin{guideline} 144 | As a rule of thumb of its usage, consider two use cases: 145 | 146 | \begin{enumerate} 147 | \item If callee \underline{always} takes ownership of the value: 148 | prefer arguments passed by value. 149 | \item If callee \underline{may} take ownership of the value: use an 150 | rvalue reference. 151 | \end{enumerate} 152 | \end{guideline} 153 | 154 | \begin{lstlisting} 155 | // "I need my own bar." 156 | void foo_copy(bar b) { /* ... */ } 157 | 158 | // "I may take ownership of b... 159 | // ...Unless I don't." 160 | void foo_rvalue(bar&& b) { /* ... */ } 161 | 162 | void baz() 163 | { 164 | bar b1; 165 | // Valid, b1 is unchanged in baz. 166 | foo_copy(b1); 167 | 168 | // Valid, we can forget about b1 now. 169 | foo_copy(std::move(b1)); 170 | 171 | bar b2; 172 | // Invalid, b2 is not an rvalue 173 | // foo_rvalue(b2); 174 | 175 | // Valid, but is b2 actually moved? 176 | foo_rvalue(std::move(b2)); 177 | } 178 | \end{lstlisting} 179 | 180 | Note that the rules above do not apply directly for functions that 181 | assign an existing resource, like a setter. In this case, always 182 | passing by value may be a pessimization if the caller does not pass an 183 | rvalue and the member assigned to releases its resource before taking 184 | the one from the argument. 185 | 186 | \begin{lstlisting} 187 | // This example does not consider small string optimization. 188 | 189 | class foo 190 | { 191 | std::string name; 192 | 193 | public: 194 | void set_name_value(std::string n) 195 | { 196 | // The internals of the name member are released, then the resources from 197 | // n are transfered. 198 | name = std::move(n); 199 | } 200 | 201 | void set_name_reference(const std::string& n) 202 | { 203 | // The value in n is copied in this->name. No allocation is done if there 204 | // is enough room for it. 205 | name = n; 206 | } 207 | }; 208 | 209 | void test_foo() 210 | { 211 | // Set up. 212 | foo f; 213 | f.set_name_value("abc"); 214 | 215 | // Behind the following call: 216 | // 1. allocate a temporary std::string on the stack. 217 | // 2. allocate the internal buffer of the temporary in the heap. 218 | // 3. copy "def" in the internal buffer. 219 | // 4. swap f.name's internals with the ones of the temporary. 220 | // 5. release the temporary's internals (previously f.name's). 221 | f.set_name_value("def"); 222 | 223 | // Behind the following call: 224 | // 1. allocate a temporary std::string on the stack. 225 | // 2. allocate the internal buffer of the temporary in the heap. 226 | // 3. copy "ghi" in the internal buffer. 227 | // 4. copy the temporary's internals into f.name. 228 | // 5. release the temporary's internals. 229 | f.set_name_reference("ghi"); 230 | 231 | // Behind the following call: 232 | // 1. allocate a temporary std::string on the stack. 233 | // 2. allocate the internal buffer of the temporary in the heap. 234 | // 3. copy the internals of name in the temporary's internals. 235 | // 4. swap f.name's internals with the ones of the temporary. 236 | // 5. release the internals of the temporary (previously f.name's). 237 | f.set_name_value(name); 238 | 239 | // Behind the following call: 240 | // 1. check that f.name is large enough for name, realloc if needed. 241 | // 2. copy the internals of name in f.name. 242 | f.set_name_reference(name) 243 | } 244 | \end{lstlisting} 245 | 246 | In all cases in the example above, it is better to pass by address. If 247 | the allocation of the temporaries is an issue, one can decide to 248 | override the setter to take an rvalue reference. 249 | 250 | %------------------------------------------------------------------------------- 251 | \subsection{\code{std::forward} and Universal References} 252 | 253 | When \code{\&\&} is used in association with a type to be deduced, 254 | like in the function below: 255 | 256 | \begin{lstlisting} 257 | template 258 | void foo(T&& arg) 259 | { 260 | /* … */ 261 | } 262 | \end{lstlisting} 263 | 264 | Then it refers neither to an rvalue-reference nor a reference. In this 265 | context, it is called a \emph{universal reference}. Depending on how 266 | the function is called then \code{T\&\&} will be either deduced to an 267 | rvalue-reference, if the argument is an rvalue, or else the references 268 | are collapsed and \code{T\&\&} becomes an lvalue-reference, just like 269 | \code{T\&}. 270 | 271 | \begin{lstlisting} 272 | void bar() 273 | { 274 | std::string s; 275 | 276 | // calls foo(std::string&) 277 | foo(s); 278 | 279 | // calls foo(std::string&&) 280 | foo(s + "abc"); 281 | } 282 | \end{lstlisting} 283 | 284 | Now how one should pass to another function an argument received as a 285 | universal reference? If it is deduced as an rvalue-reference, then 286 | \code{std::move()} should be used, otherwise it should be passed as 287 | is. 288 | 289 | \marginheader{}% 290 | % 291 | Fortunately \cpp11 provides \code{std::forward()} to do the check for 292 | us: 293 | 294 | \begin{lstlisting} 295 | template 296 | void foo(T&& arg) 297 | { 298 | // Pass as an rvalue-reference or by address, whichever fits. 299 | foobar(std::forward(arg)); 300 | } 301 | \end{lstlisting} 302 | -------------------------------------------------------------------------------- /parts/11/nullptr.tex: -------------------------------------------------------------------------------- 1 | \subsection{\code{std::nullptr\_t} and \code{nullptr}} 2 | 3 | \problemtitle 4 | 5 | The traditional way to set a pointer to zero before \cpp11 was via the 6 | \code{NULL} macro. So what would happen if we tried to compile the 7 | following program? 8 | 9 | \lstinputlisting{examples/nullptr/nullptr-98.cpp} 10 | 11 | Did you expect the program to compile well and \code{foo(int*)} to be 12 | called? Too bad, we are in a good old ambiguous call situation: 13 | 14 | \begin{lstlisting}[language=bash] 15 | error: call of overloaded ‘foo(NULL)’ is ambiguous 16 | \end{lstlisting} 17 | 18 | Since \code{NULL} is often defined as the integral value zero, the 19 | compiler cannot distinguish it from an integer. Thus the error. 20 | 21 | \solutiontitle 22 | 23 | \marginheader{}% 24 | % 25 | As an answer to this problem, \cpp11 introduces the \code{nullptr} 26 | keyword, which exactly represents a zero pointer. Its type is 27 | \code{std::nullptr\_t} and it is implicitly convertible to any 28 | pointer. Consequently, the code below compiles as expected. 29 | 30 | \lstinputlisting[emph=nullptr]{examples/nullptr/nullptr-11.cpp} 31 | 32 | Note that \code{nullptr} is a keyword available without prior 33 | definition. Its type, on the other hand, is defined in header 34 | \code{cstddef}. 35 | -------------------------------------------------------------------------------- /parts/11/override-and-final.tex: -------------------------------------------------------------------------------- 1 | \subsection{Override and Final} 2 | 3 | \problemtitle 4 | 5 | So we have a class in our \cpp-98 code base that looks like that: 6 | 7 | \begin{lstlisting} 8 | struct abstract_concrete_base 9 | { 10 | virtual ~abstract_concrete_base(); 11 | virtual void consume(); 12 | }; 13 | \end{lstlisting} 14 | 15 | Down the hierarchy we have some class that overrides the 16 | \code{consume()} function\footnote{You may also find versions of this 17 | pattern in the wild where the \code{virtual} keyword is repeated in 18 | the derived classes, so the reader can suppose that it is an 19 | overridden function without looking at the declaration of the parent 20 | class.}: 21 | 22 | \begin{lstlisting} 23 | struct serious_business : abstract_concrete_base 24 | { 25 | void consume(); 26 | }; 27 | \end{lstlisting} 28 | 29 | Suddenly, the base class has some work to do in \code{consume()} 30 | regardless of the details of the derived classes. Also, it is well 31 | known that one should prefer non-virtual public functions calling 32 | virtual private functions, so let's update our code: 33 | 34 | \begin{lstlisting} 35 | struct abstract_concrete_base 36 | { 37 | virtual ~abstract_concrete_base(); 38 | 39 | void consume() 40 | { 41 | stuff_from_base_class(); 42 | do_consume(); 43 | } 44 | 45 | private: 46 | void stuff_from_base_class(); 47 | virtual void do_consume(); 48 | }; 49 | \end{lstlisting} 50 | 51 | Nice. Everything compiles well but all derived classes are broken. It 52 | turns out that since \code{do\_consume()} is not a pure virtual 53 | function, there is no problem to instantiate the class. All derived 54 | will use the default \code{do\_consume()} and their old 55 | \code{consume()} is now just another function of theirs. 56 | 57 | Wouldn't it be nice if there was a way to detect the problem? 58 | 59 | \solutiontitle 60 | 61 | That's why the \code{override} keyword has been introduced in 62 | \cpp11. By modifying the initial implementation of 63 | \code{serious\_business} as follows: 64 | 65 | \begin{lstlisting} 66 | struct serious_business : abstract_concrete_base 67 | { 68 | void consume() @\emcode{override}@; 69 | }; 70 | \end{lstlisting} 71 | 72 | The programmer explicitly tells the compiler that this function is 73 | expected to override the same function from a parent class. So when 74 | \code{abstract\_concrete\_base} is updated and its \code{consume()} 75 | function becomes non-virtual, the compiler will immediately complain 76 | that the function from \code{serious\_business} does not override 77 | anything. Good! 78 | 79 | \bigskip 80 | 81 | Another keyword related to inheritance and function overriding has 82 | been introduced in \cpp11: the \code{final} keyword. When used in 83 | place of \code{override}, it tells the compiler that the function 84 | should not be overridden in the derived classes. Previously a virtual 85 | function could be overridden anywhere from the top to the bottom of 86 | the hierarchy. Now if one declaration is marked as final, the derived 87 | classes are not allowed to redefine the function anymore. 88 | 89 | Additionally, one can place the \code{final} keyword after the name of 90 | a class to indicate that this class cannot be derived at all: 91 | 92 | \begin{lstlisting} 93 | struct serious_business @\emcode{final}@ : abstract_concrete_base 94 | { 95 | void consume() override; 96 | }; 97 | \end{lstlisting} 98 | -------------------------------------------------------------------------------- /parts/11/prev-next.tex: -------------------------------------------------------------------------------- 1 | \subsection{Iterator Successors and Predecessors} 2 | 3 | \problemtitle 4 | 5 | There are many kind of iterators: forward iterators, that can be 6 | incremented one step at a time with \code{operator++}, bidirectional 7 | iterators, that can additionally be decremented with 8 | \code{operator--}, and random access iterators, that can be 9 | incremented or decremented by any amount at once. 10 | 11 | When writing a function taking an iterator whose type is templated, 12 | incrementing an iterator by more than one unit cannot be done 13 | directly, as it would fail for non-random iterators. Prior to \cpp11, 14 | this was done with \code{std::advance()}. 15 | 16 | \begin{lstlisting} 17 | template 18 | void every_n_items 19 | (Iterator it, std::size_t count, std::size_t step, F f) 20 | { 21 | for (; count > step; count -= step) 22 | { 23 | f(*it); 24 | std::advance(it, step); 25 | } 26 | } 27 | \end{lstlisting} 28 | 29 | \code{std::advance()} accepts a negative distance, in which case it 30 | will advance… hum… backwards. Note that the function modifies its 31 | argument, so using it to get another iterator from a given one is 32 | cumbersome: 33 | 34 | \begin{lstlisting} 35 | template 36 | void inplace_adjacent_sums(Iterator first, const Iterator& last) 37 | { 38 | if (first == last) 39 | return; 40 | 41 | // Two steps to get an iterator on the second element. Ideally we 42 | // would have wanted to limit its scope to the loop too. 43 | Iterator second = first; 44 | std::advance(second, 1); 45 | 46 | for (; second != last; ) 47 | { 48 | *first += *second; 49 | first = second; 50 | std::advance(second, 1); 51 | } 52 | } 53 | \end{lstlisting} 54 | 55 | \solutiontitle 56 | 57 | \marginheader{}% 58 | % 59 | \Cpp11 introduces the replacement functions \code{std::prev()} and 60 | \code{std::next()}, which are mostly here to make things clear and 61 | more convenient. The former is to be used to move the iterator 62 | backwards, while the latter is used to move it forward. If no distance 63 | is passed, then it defaults to one. 64 | 65 | Note that they return a copy of the new iterator, instead of modifying 66 | its argument. 67 | 68 | \begin{lstlisting} 69 | template 70 | void inplace_adjacent_sums(Iterator first, const Iterator& last) 71 | { 72 | if (first == last) 73 | return; 74 | 75 | // Here we can initialize the second iterator in the loop, reducing 76 | // its scope. 77 | for (Iterator second = @\emcode{std::next}@(first); second != last; ) 78 | { 79 | *first += *second; 80 | first = second; 81 | std::advance(second, 1); 82 | } 83 | } 84 | \end{lstlisting} 85 | -------------------------------------------------------------------------------- /parts/11/random.tex: -------------------------------------------------------------------------------- 1 | \subsection{Random} 2 | 3 | \problemtitle 4 | 5 | Getting random numbers in \cpp{} was historically done by using 6 | functions from the C library. First we initialized the a global 7 | generator via a call to \code{srand()} then the values were generated 8 | via \code{rand()}. 9 | 10 | Unfortunately this generator was known for being a quite poor one. 11 | 12 | \solutiontitle 13 | 14 | \marginheader{}% 15 | % 16 | This has been greatly improved in \cpp11. For the initialization, we 17 | now have \code{std::random\_device} to access a hardware-based 18 | generator\footnote{If there is one, otherwise it would be 19 | software-based.}, then there are many pseudo-random number 20 | generators, \code{std::mt19937} being a quite popular one. 21 | 22 | \begin{lstlisting} 23 | int main() 24 | { 25 | // The random device will get a random value from the system. It is 26 | // certainly the best random source we can have here. 27 | std::random_device seed; 28 | 29 | // This is a pseudo-random number generator, here initialized by 30 | // a value obtained from the random device. 31 | std::mt19937 generator(seed()); 32 | 33 | // Finally this distribution will project the random values in the 34 | // [1, 24] range with equiprobability for each value. 35 | std::uniform_int_distribution range(1, 10); 36 | 37 | for (int i = 0; i != 1000; ++i) 38 | printf("%d\n", range(generator)); 39 | 40 | return 0; 41 | } 42 | \end{lstlisting} 43 | 44 | Unfortunately the generators available in the standard library are 45 | known to be both inefficient and not very good at randomness. As an 46 | alternative, we can check for a permuted congruential generator (PCG) 47 | \cite{pcg}, at \url{https://www.pcg-random.org/}. 48 | -------------------------------------------------------------------------------- /parts/11/range-based-for-loops.tex: -------------------------------------------------------------------------------- 1 | %------------------------------------------------------------------------------- 2 | \subsection{Range-based For Loops} 3 | \label{range-based-for-loops} 4 | 5 | \problemtitle 6 | 7 | Before \cpp11, if someone wanted to iterate over a container, he had 8 | to construct an iterator, of the correct type with respect to the 9 | container, and write the loop with the classical three steps: 10 | initialization (get an iterator on the begining of the container), 11 | stopping condition (the iterator has not reached the end), and the 12 | loop increment. 13 | 14 | \begin{lstlisting} 15 | void multiply(std::vector& v, int c) 16 | { 17 | // I'm going to iterate over v, so I need an iterator. 18 | typedef std::vector::iterator it_t; 19 | const it_t end(v.end()); 20 | 21 | for (it_t it(v.begin()); it != end; ++it) 22 | *it *= c; 23 | } 24 | \end{lstlisting} 25 | 26 | \solutiontitle 27 | 28 | All of this was quite verbose and repetitive when using standard 29 | containers. Starting from \cpp11, all this administrative stuff can be 30 | avoided by using a ranged-based for loop. 31 | 32 | \begin{lstlisting} 33 | void multiply(std::vector& v, int c) 34 | { 35 | // Just get all entries from v. 36 | for (int& vi : v) 37 | vi *= c; 38 | } 39 | \end{lstlisting} 40 | 41 | This format uniformizes iteration over anything having a begining and 42 | an end. Moreover, it handles the typical subtleties of for loops for 43 | you: the end of the container is guaranteed to be computed only once 44 | and the increment use the preincrement operator. 45 | -------------------------------------------------------------------------------- /parts/11/reference-wrapper.tex: -------------------------------------------------------------------------------- 1 | \subsection{Reference Wrapper} 2 | 3 | \problemtitle 4 | 5 | Be it \cpp11 or before, template argument deduction never pick a 6 | reference. So, for example, if we wanted to create an 7 | \code{std::pair}, we could not use \code{std::make\_pair}: 8 | 9 | \begin{lstlisting} 10 | int a; 11 | int b; 12 | 13 | // Ok in C++11, not before. The members of the pair are references to 14 | // a and b. 15 | std::pair pair_1(a, b); 16 | 17 | // Not ok, std::make_pair returns an std::pair. 18 | std::pair pair_2 = std::make_pair(a, b); 19 | 20 | // Not ok in C++11 and before, for different reasons. 21 | std::pair pair_3 = std::make_pair(a, b); 22 | \end{lstlisting} 23 | 24 | \solutiontitle 25 | 26 | \marginheader{}% 27 | % 28 | The \code{std::ref()} function (as well as \code{std::cref()}) 29 | introduced in \cpp11 will help us with this problem. They both create 30 | a reference wrapper for their argument (non const or const, 31 | respectively), that is implicitly convertible to a raw reference. 32 | 33 | \begin{lstlisting} 34 | int a; 35 | int b; 36 | 37 | // Ok, std::make_pair returns an 38 | // std::pair>, which is itself 39 | // convertible to std::pair. 40 | std::pair pair_make = std::make_pair(a, @\emcode{std::ref(b)}@); 41 | \end{lstlisting} 42 | 43 | This is especially useful when binding variables that we don't want 44 | to copy. 45 | 46 | \lstinputlisting{examples/reference-wrapper/capacity_tracker.cpp} 47 | -------------------------------------------------------------------------------- /parts/11/rvalue-reference.tex: -------------------------------------------------------------------------------- 1 | \subsection{Rvalue References} 2 | 3 | \problemtitle 4 | 5 | In the function \code{build\_widget()} below, a temporary string is 6 | created by the code \code{label + "def"}, then a reference to this 7 | string is passed to the constructor of \code{widget}, where it is then 8 | copied in \code{widget::m\_label}. Finally, the temporary is deleted. 9 | 10 | \begin{lstlisting} 11 | struct widget 12 | { 13 | widget(const std::string& label) 14 | : m_label(label) 15 | {} 16 | 17 | std::string m_label; 18 | }; 19 | 20 | void build_widget() 21 | { 22 | std::string label("abc"); 23 | widget w(label + "def"); 24 | } 25 | \end{lstlisting} 26 | 27 | Temporaries have the interesting property that they have no use but to 28 | be consumed by an expression building another value. In other words, 29 | in the example above, the purpose of the result of \code{label + 30 | "def"} is to end up in \code{widget::m\_label}. So why do we need a 31 | copy? It would be more efficient to just pass the instance created by 32 | the concatenation directly to the final variable. 33 | 34 | \solutiontitle 35 | 36 | To solve this problem, \cpp11 introduces the concept of rvalue 37 | references, which are, to put it simply, references to 38 | temporaries. These references are denoted with a double ampersand 39 | \code{\&\&}. See the updated example, below: 40 | 41 | \begin{lstlisting} 42 | struct widget 43 | { 44 | widget(@\emcode{std::string\&\&}@ label) 45 | : m_label(label) 46 | {} 47 | 48 | std::string m_label; 49 | }; 50 | 51 | void build_widget() 52 | { 53 | std::string label("abc"); 54 | widget f(label + "def"); 55 | } 56 | \end{lstlisting} 57 | 58 | The signature of the constructor indicates that it accept temporaries 59 | as arguments. However, this code is not enough to avoid copies of the 60 | string yet, as the instruction \code{m\_label(label)} still copies the 61 | string. The next step is to replace this instruction with 62 | \code{m\_label(std::move(label))}, and then we will have no copy. This 63 | is the topic of section \ref{move}. 64 | 65 | Note that if the constructor's argument was \code{widget}, like in 66 | \code{widget(widget\&\& that)}, then this would declare what is called 67 | a move-constructor. This is a distinct constructor than the 68 | copy-constructor and it is explicitly allowed to steal the internals 69 | of its argument, as long as the instance behind the argument stays in 70 | a valid state. 71 | 72 | -------------------------------------------------------------------------------- /parts/11/scoped-enumerations.tex: -------------------------------------------------------------------------------- 1 | \subsection{Scoped Enumerations} 2 | 3 | \problemtitle 4 | 5 | An enumeration in pre-\cpp11 code is just like a C enumeration: a list 6 | of constants of type \code{int} in the scope containing the 7 | enumeration. For example, note how \code{appliance::fan} can be 8 | accessed directly and assigned to an integer in the code below: 9 | 10 | \begin{lstlisting} 11 | enum appliance 12 | { 13 | fan, 14 | oven 15 | }; 16 | 17 | int main() 18 | { 19 | int v = fan; 20 | return 0; 21 | } 22 | \end{lstlisting} 23 | 24 | While this is nice when we actually want the values of the 25 | enumeration to be an alias for integer constants, for example to store 26 | bit field flags, it can quickly become a mess when the entries of 27 | different enumerations share the same identifier in the same scope. 28 | 29 | \begin{lstlisting} 30 | enum appliance 31 | { 32 | fan, 33 | oven 34 | }; 35 | 36 | enum follower 37 | { 38 | fan, 39 | admirer 40 | }; 41 | \end{lstlisting} 42 | 43 | The above code will fail to compile with a message along the lines of 44 | ``error: ‘fan’ conflicts with a previous declaration.'' Now the 45 | typical solution to that was to add a unique prefix to the enumerated 46 | values, but in the times of namespaces and so, is it really a solution? 47 | 48 | \solutiontitle 49 | 50 | A scoped enumeration as introduced in \cpp11 is declared by adding the 51 | \code{class} or \code{struct} keyword between \code{enum} and the 52 | identifier. Additionally the storage type of the values can be defined 53 | too: 54 | 55 | \begin{lstlisting} 56 | enum @\emcode{class}@ appliance 57 | { 58 | fan, 59 | oven 60 | }; 61 | 62 | enum @\emcode{class}@ follower : @\emcode{char}@ 63 | { 64 | fan, 65 | admirer 66 | }; 67 | \end{lstlisting} 68 | 69 | With these declarations the values are scoped in their respective 70 | enumerations and do not conflict with each other; so if we want to 71 | access a value we must now prefix it with the name of the enumeration, 72 | like in \code{follower::fan}. Moreover, they are also not implicitly 73 | convertible to \code{int} anymore, which may or may not always be a 74 | good thing. 75 | 76 | The fact that we can also define the type of their values allows for 77 | smaller memory consumption when needed, but also add the possibility 78 | to use longer-than-\code{int} values. Nevertheless, I usually don't 79 | specify this type unless necessary since it has to be repeated when 80 | the enumeration is forward declared. This repetition adds coupling and 81 | complicates any change in the type, for something that look like 82 | implementation details to me. 83 | 84 | -------------------------------------------------------------------------------- /parts/11/smart-pointers.tex: -------------------------------------------------------------------------------- 1 | \subsection{Smart Pointers} 2 | 3 | Memory allocation in \cpp{} is a tough subject, dynamic allocation 4 | being the hardest part. 5 | 6 | Before \cpp11, the programmer had to be very careful with the life 7 | span of dynamically allocated memory in order to, first, be sure that 8 | it is released at some point and, second, that no access is made to it 9 | once it has been released, not even another release. 10 | 11 | See how many problems could occur with this short snippet: 12 | 13 | \begin{lstlisting} 14 | struct foo 15 | { 16 | foo(int* p) 17 | : m_p(p) 18 | {} 19 | 20 | ~foo() 21 | { 22 | delete m_p; 23 | } 24 | 25 | private: 26 | int* m_p; 27 | }; 28 | 29 | void bar() 30 | { 31 | foo f1(new int); 32 | foo f2(f1); 33 | 34 | int* p1(new int); 35 | } 36 | \end{lstlisting} 37 | 38 | There are two problems with this code. First, \code{foo} does not 39 | define nor disable its copy constructor, so, by default, its 40 | \code{m\_p} pointer will be copied to the new instance. Then, when the 41 | original instance and its copy will be destroyed, both will call 42 | \code{delete} on the same pointer. This is what will happen with 43 | \code{f1} and its copy \code{f2}. In the best scenario the program 44 | would crash here. 45 | 46 | The second problem is \code{p1}. This pointer points to a dynamically 47 | allocated \code{int} for which no \code{delete} is written. When the 48 | pointer will go out of scope then there will be no way to release the 49 | allocated memory. 50 | 51 | %------------------------------------------------------------------------------- 52 | \subsubsection{Self-Deleting Non-Shared Pointer} 53 | \label{sec:unique_ptr} 54 | 55 | \marginheader{}% 56 | % 57 | \Cpp11 introduces a pointer wrapper named \code{std::unique\_ptr}, 58 | which has the merit of automatically calling \code{delete} on the 59 | pointer upon destruction. Applied to the previous example, it would 60 | solve one problem and force us to find a solution for the other: 61 | 62 | \begin{lstlisting} 63 | struct foo 64 | { 65 | foo(std::unique_ptr p) 66 | : m_p(std::move(p)) 67 | {} 68 | 69 | // The default destructor does the job. 70 | 71 | private: 72 | std::unique_ptr m_p; 73 | }; 74 | 75 | void bar() 76 | { 77 | std::unique_ptr p1(new int); 78 | 79 | foo f1(std::unique_ptr(new int)); 80 | foo f2(std::move(f1)); 81 | } 82 | \end{lstlisting} 83 | 84 | This program is undoubtedly safer than the previous one. The copy 85 | constructor of \code{foo} is still not defined, but it is for sure 86 | deleted since \code{std::unique\_ptr} has no copy constructor 87 | neither. So, by default, we cannot share the resource between two 88 | instances, which is great. The only solution here is to either 89 | allocate a new int for \code{f2} or steal the one from {f1}. The 90 | latter is implemented here. 91 | 92 | Then, for the release of \code{p1}, it is automatically done when the 93 | variable leaves the scope, so no memory is leaked. 94 | 95 | \bigskip 96 | 97 | One of the best features of \code{std::unique\_ptr} is the possibility 98 | to use a custom deleter to release the pointer. This makes this smart 99 | pointer a tool of choice when using C-like resources. 100 | 101 | Check for example the use case of libavcodec's 102 | \code{AVFormatContext}. The format context is obtained via a call to 103 | \code{avformat\_open\_input(AVFormatContext**, const char*, 104 | AVInputFormat*, AVDictionary**)} and must be released by a call to 105 | \code{avformat\_close\_input(AVFormatContext**)}. With the help of 106 | \code{std::unique\_ptr} this could be done as follows: 107 | 108 | \begin{lstlisting} 109 | namespace detail 110 | { 111 | static void close_format_context(AVFormatContext* context); 112 | } 113 | 114 | void foo(const char* path) 115 | { 116 | AVFormatContext* raw_context_pointer(nullptr); 117 | 118 | const int open_result = 119 | avformat_open_input 120 | (&raw_context_pointer, path, nullptr, nullptr); 121 | 122 | std::unique_ptr 123 | < 124 | AVFormatContext, 125 | decltype(&detail::close_format_context) 126 | > 127 | context_pointer 128 | (raw_context_pointer, &detail::close_format_context); 129 | 130 | // … 131 | } 132 | \end{lstlisting} 133 | 134 | With this approach, the format context will be released via a call to 135 | \code{detail::close\_format\_context} as soon as 136 | \code{context\_pointer} leaves the scope. Do we know if the memory 137 | pointed by \code{raw\_context\_pointer} is dynamically allocated? We 138 | do not, and it does not matter. What we have here is a simple robust 139 | way to attach a release function to an acquired resource. 140 | 141 | %------------------------------------------------------------------------------- 142 | \subsubsection{Self-Deleting Shared Pointer} 143 | 144 | \marginheader{}% 145 | % 146 | I have a hard time trying to find a use case where 147 | \code{std::shared\_ptr} is the best solution, so let's just focus on a 148 | good-enough solution. 149 | 150 | This smart pointer is the answer to the problem of having a 151 | dynamically allocated resource that may outlive its creator, and that 152 | may also be accessed from two independent owners. In this case, the 153 | ownership of the resource is unclear, as it is \emph{shared}, so the 154 | idea is to keep the resource alive until all its owner release it. 155 | 156 | For example, let's say we have a function whose role is to dispatch a 157 | message to multiple listeners, whom will not process it right now. For 158 | some reason the message cannot be copied, so we cannot send a copy of 159 | it to everyone: 160 | 161 | \begin{lstlisting} 162 | void dispatch_message 163 | (const std::vector& listeners, 164 | const std::string& raw) 165 | { 166 | message m = parse_message(raw); 167 | std::shared_ptr p 168 | (std::make_shared(std::move(m))); 169 | 170 | for(listener* l : listeners) 171 | listener->add_to_queue(m); 172 | } 173 | \end{lstlisting} 174 | 175 | With this implementation the message outlives the scope of 176 | \code{dispatch\_message()} and will remain in memory until all 177 | listeners have released it. 178 | 179 | Is it the best solution for this problem? Honestly I doubt 180 | that. Actually, most uses of \code{std::shared\_ptr} I have seen, 181 | including mine, looked a bit like a lack of reasoning about resource 182 | management. 183 | 184 | Wouldn't it have been better if the dispatching and the listeners were 185 | scheduled in a loop and if the dispatcher would own the messages for 186 | some iterations, or until they would be marked as processed by the 187 | listeners? Do we really have to pay for dynamic allocations here? 188 | 189 | \begin{guideline} 190 | When you find yourself thinking that a shared resource with no clear 191 | life span — a \code{std::shared\_ptr} — is a good answer to your 192 | problem, please double check your solution, and ask for a second 193 | opinion. 194 | \end{guideline} 195 | 196 | \begin{pitfall} 197 | Many documentations declare, rightfully, that \code{std::shared\_ptr} 198 | is thread-safe, and I have seen people using it to \emph{safely} 199 | access the allocated resource in a concurrent way. 200 | 201 | \bigskip 202 | 203 | It must be said that the only thread-safe part in a 204 | \code{std::shared\_ptr} is its reference counter. 205 | 206 | \bigskip 207 | 208 | Nothing is done — nothing can be done — to provide an automatic 209 | thread-safe access to the allocated resource. Actually, even having 210 | two threads doing respectively a copy (i.e.\ \code{std::shared\_ptr 211 | p(sp)}) and a deletion (i.e.\ \code{sp.release()}), for the same 212 | shared pointer \code{sp}, has no defined outcome without additional 213 | synchronization. The only guarantee is that the increment of the 214 | counter in the copy won't be done between the decrement and the 215 | deletion from the release. 216 | 217 | \end{pitfall} 218 | 219 | %------------------------------------------------------------------------------- 220 | \subsubsection{Shared Pointer Observer} 221 | 222 | \marginheader{}% 223 | % 224 | What happens when the instance pointed by a \code{std::shared\_ptr} 225 | owns a \code{std::shared\_ptr} pointing to the owner of the former? 226 | Then we have a cycle and none of the instances will be released. 227 | 228 | \begin{lstlisting} 229 | struct foo; 230 | 231 | struct bar 232 | { 233 | std::shared_ptr m_foo; 234 | }; 235 | 236 | struct foo 237 | { 238 | std::shared_ptr m_bar; 239 | }; 240 | 241 | void foobar() 242 | { 243 | std::shared_ptr f(std::make_shared()); 244 | std::shared_ptr b(std::make_shared()); 245 | b->m_foo = f; 246 | f->m_bar = b; 247 | 248 | // The instances pointed by foo and foo->bar won't be deleted. 249 | } 250 | \end{lstlisting} 251 | 252 | In order to break this kind of dependency loop, one pointer should be 253 | declared as an \code{std::weak\_ptr}. Just like 254 | \code{std::shared\_ptr}, this smart pointer is here to point to a 255 | shared resource, except that it does not count as an owner of the 256 | resource. Additionally, it provides a way to test if the resource is 257 | still available via the \code{std::weak\_ptr::lock()} function, which 258 | returns a shared pointer on the resource if it is available, or 259 | \code{nullptr} otherwise. 260 | 261 | \begin{lstlisting} 262 | struct foo; 263 | 264 | struct bar 265 | { 266 | @\emcode{std::weak\_ptr}@ m_foo; 267 | }; 268 | 269 | struct foo 270 | { 271 | std::shared_ptr m_bar; 272 | }; 273 | 274 | void foobar() 275 | { 276 | std::shared_ptr f(std::make_shared()); 277 | std::shared_ptr b(std::make_shared()); 278 | b->m_foo = f; 279 | f->m_bar = b; 280 | 281 | { 282 | std::shared_ptr resource(b->m_foo.lock()); 283 | if (resource) 284 | printf("This message is printed.\n"); 285 | } 286 | 287 | f.reset(); 288 | 289 | std::shared_ptr resource(b->m_foo.lock()); 290 | 291 | if (resource) 292 | printf("This message is not.\n"); 293 | } 294 | \end{lstlisting} 295 | -------------------------------------------------------------------------------- /parts/11/static-assert.tex: -------------------------------------------------------------------------------- 1 | \subsection{Compile-Time Assertions} 2 | 3 | \problemtitle 4 | 5 | Compile-time assertions, declared with a \code{static\_assert}, are a 6 | way to verify a property at compile time. 7 | 8 | For example, the code below declares a type with an array whose size, 9 | with respect to the type's name, must be even: 10 | 11 | \begin{lstlisting} 12 | template 13 | struct even_sized_array 14 | { 15 | typedef T type[N]; 16 | }; 17 | \end{lstlisting} 18 | 19 | How can we ensure that \code{N} is always even? Before \cpp11 a 20 | solution to that would have been to enter some template dance such 21 | that passing an odd value would instantiate an incomplete type. 22 | 23 | \lstinputlisting{examples/static-assert/even_sized_array-98.cpp} 24 | 25 | Not only this is verbose, but these kind of template instantiation 26 | errors are well known for producing kilometer-long unbearable error 27 | messages. 28 | 29 | \solutiontitle 30 | 31 | Enters \code{static\_assert} in \cpp11. Just like the good old 32 | \code{assert(condition)} would check that the given condition is true 33 | at run time, \code{static\_assert(condition, message)} will check the 34 | condition during the compilation. 35 | 36 | \lstinputlisting{examples/static-assert/even_sized_array-11.cpp} 37 | 38 | This is very less verbose than previously and it actually carries the 39 | intent. The error message is also clearer, as it is just something 40 | like ``static assertion failed: the message''. 41 | -------------------------------------------------------------------------------- /parts/11/template-aliases.tex: -------------------------------------------------------------------------------- 1 | %------------------------------------------------------------------------------- 2 | \subsection{Template Aliases} 3 | 4 | \problemtitle 5 | 6 | Before \cpp11, we could simply not declare a typedef with a 7 | parameterized type. For example, the following did not work: 8 | 9 | \begin{lstlisting} 10 | // We cannot do that. 11 | template 12 | typedef std::vector collection; 13 | 14 | // We cannot do that either. 15 | template 16 | typedef std::map string_map; 17 | \end{lstlisting} 18 | 19 | The alternative was to use a struct to receive the type, then declare 20 | the typedef inside the struct: 21 | 22 | \begin{lstlisting} 23 | // Workaround: nest the type. 24 | template 25 | struct string_map 26 | { 27 | typedef std::map type; 28 | }; 29 | 30 | // Easy to use, isn't it? 31 | string_map::type string_to_int; 32 | \end{lstlisting} 33 | 34 | \solutiontitle 35 | 36 | Starting with \cpp11, the \code{using} keywork allows to declare 37 | templated type aliases: 38 | 39 | \begin{lstlisting} 40 | // We can do that. 41 | template 42 | @\emcode{using}@ collection = std::vector; 43 | 44 | // We can also do that. 45 | template 46 | @\emcode{using}@ string_map = std::map; 47 | 48 | // Looks like a first-class type. 49 | string_map string_to_int; 50 | \end{lstlisting} 51 | 52 | The using keyword is also a replacement for typedef in general. 53 | -------------------------------------------------------------------------------- /parts/11/thread.tex: -------------------------------------------------------------------------------- 1 | \subsection{Threads} 2 | 3 | \problemtitle 4 | 5 | Before \cpp11 there was just nothing in the standard library to 6 | execute a thread, so we had to either go native with pthreads, Windows 7 | threads, or whatever fit our need, or else we could use an independent 8 | library that would do the system abstraction for us, like Boost.Thread. 9 | 10 | \solutiontitle 11 | 12 | \marginheader{}% 13 | % 14 | Thankfully, \cpp11 came with \code{std::thread}, which does the system 15 | abstraction for us and allows us to write portable threaded 16 | code\footnote{When the targeted platform supports it. I'm looking at 17 | you WebAssembly!}. Launching a thread is as simple as this: 18 | 19 | \begin{lstlisting} 20 | auto expensive_computation = 21 | []() -> void 22 | { 23 | // This infinite loop takes forever to complete! It slows down 24 | // our awesome app, better put it in a thread. 25 | while (true); 26 | }; 27 | 28 | @\emcode{std::thread t(expensive\_computation);}@ 29 | // Here we go, the thread is running. 30 | \end{lstlisting} 31 | 32 | \marginheader{,\\ 33 | }% 34 | % 35 | With the threads come the mutexes, condition variables, and more, that 36 | will help us write synchronization points. Here is a more complete 37 | example with two threads accessing shared data: 38 | 39 | \lstinputlisting{examples/thread/flood.cpp} 40 | -------------------------------------------------------------------------------- /parts/11/tuple.tex: -------------------------------------------------------------------------------- 1 | \subsection{Tuple} 2 | \label{sec:tuple} 3 | 4 | \problemtitle 5 | 6 | The type \code{std::pair} is a nice utility class available in the STL 7 | since forever. It is a struct accepting two template parameters and 8 | defining two fields of these types, named ``first'' and 9 | ``second''. Approximately like: 10 | 11 | \begin{lstlisting} 12 | template 13 | struct pair 14 | { 15 | T1 first; 16 | T2 second; 17 | }; 18 | \end{lstlisting} 19 | 20 | It is for example the value type of associative containers like 21 | \code{std::map}, and now we are stuck with map entries with fields 22 | named ``first'' and ``second'' while something like ``key'' and 23 | ``value'' would have carried the semantics better. Meh. Well, it may 24 | not be the most expressive but at least we are reusing code via this 25 | hyper generic reusable type, hooray! 26 | 27 | Sorry, I inadvertently switched the rant-mode button on\footnote{That 28 | being said, I actually love the fact that even for small types like 29 | that effort is made by \cpp{} developers to build more efficient 30 | implementations. Search for \emph{compressed pair} or \emph{tight 31 | pair} for example.}. 32 | 33 | \solutiontitle 34 | 35 | Generalizing this structure to any number of fields/types was quite 36 | complex, as before the arrival of variadic templates 37 | \aref{variadic-template} in \cpp11 we had to go through some type lists 38 | and other metaprogramming dances. 39 | 40 | \marginheader{}% 41 | % 42 | Thanks to their introduction, generalizing \code{std::pair} to any 43 | number of elements is now somewhat simpler, and it is already done in 44 | the STL via \code{std::tuple}. Additionally, \code{std::make\_tuple()} 45 | is a utility function that can create a tuple from its values, 46 | deducing the actual tuple type from its arguments. Finally, the main 47 | companion function to \code{std::tuple} is \code{std::get()}, which 48 | allows to access a tuple element by its index. 49 | 50 | \begin{lstlisting} 51 | // Creating a tuple explicitly. 52 | std::tuple t(24, 42.f, true); 53 | 54 | // Creating a tuple from its values. 55 | t = std::make_tuple(42, 24.f, false); 56 | 57 | // Accessing the elements in a tuple. 58 | printf("%f\n", std::get<1>(t)); 59 | std::get<2>(t) = false; 60 | \end{lstlisting} 61 | 62 | Additionally, \code{std::tie()} is a helper function which creates a 63 | tuple whose elements are references to the arguments passed to the 64 | function. 65 | 66 | \begin{lstlisting} 67 | // Swap the first mismatching elements from two vectors. 68 | void swap_first_mismatch(std::vector& v1, std::vector& v2) 69 | { 70 | using iterator = std::vector::iterator; 71 | 72 | iterator it_v1; 73 | iterator it_v2; 74 | 75 | // std::mismatch() returns a pair of iterators. We assign this pair 76 | // to a tuple whose elements are references to the two variables 77 | // declared above, meaning that we actually assign the variables. 78 | std::tie(it_v1, it_v2) = std::mismatch(v1.begin(), v1.end(), v2.begin()); 79 | 80 | std::swap(*it_v1, *it_v2); 81 | } 82 | \end{lstlisting} 83 | 84 | \bigskip 85 | 86 | Declaring a tuple in a \cpp{} program typically happen for few reasons: 87 | \begin{itemize} 88 | \item By laziness where a struct could have been used\footnote{Don't 89 | do that.}, 90 | \item To return multiple values from a function: 91 | \code{std::tuple get\_dimensions()}\footnote{Don't do 92 | that either, just write a meaningful type.}. 93 | \item To lure Python developers into writing \cpp{}\footnote{But… why 94 | should we lure them if it's not their kind of stuff?}. 95 | \item To group types, to carry type lists, in metaprogramming context. 96 | \end{itemize} 97 | 98 | \begin{guideline} 99 | If you ever end up in a situation where \code{std::tuple} seems to be 100 | the best type for an aggregate value, please reconsider. 101 | 102 | Naming things is hard, but having a named struct will be better to 103 | carry the meaning to the next readers than presenting them a bunch of 104 | data thrown in a bag. 105 | \end{guideline} 106 | 107 | It is thus quite difficult to find a good short example for 108 | \code{std::tuple}. One good example could be argument binding, but 109 | it's a quite long example that needs many extra features. Another 110 | example is found in one constructor of \code{std::pair}, which allows 111 | to directly pass the arguments to use to construct its fields: 112 | 113 | \begin{lstlisting} 114 | template 115 | struct pair 116 | { 117 | // Simplified for the example. 118 | template 119 | pair 120 | (std::tuple first_args, std::tuple second_args) 121 | : first(/* here we pass the content of first_args */), 122 | second(/* here we pass the content of second_args */) 123 | {} 124 | \end{lstlisting} 125 | 126 | Yet another example is a metaprogramming use case where multiple 127 | parameter packs must be passed to a type or function: 128 | 129 | \begin{lstlisting} 130 | // This won't work since the compiler cannot tell where to split the 131 | // As and Bs 132 | template 133 | struct failing_multi_pack 134 | {}; 135 | 136 | // The code below will work though. 137 | 138 | // This one is just the base template declaration, not defined. 139 | template 140 | struct working_multi_pack; 141 | 142 | // And we can specialize it for tuples. Now the compiler can split As 143 | // and Bs. 144 | template 145 | struct working_multi_pack, std::tuple> 146 | {}; 147 | \end{lstlisting} 148 | 149 | Well, I can see that you are a bit disappointed. Let's have a look at 150 | the binding stuff. Hold on, it is not simple (still incomplete however): 151 | 152 | \label{example:argument-binding} 153 | \lstinputlisting{examples/tuple/binding.cpp} 154 | -------------------------------------------------------------------------------- /parts/11/type-traits.tex: -------------------------------------------------------------------------------- 1 | \subsection{Type Traits} 2 | 3 | \problemtitle 4 | 5 | Let's have a look at this small function: 6 | 7 | \begin{lstlisting} 8 | template 9 | T mix(T a, T b, T r) 10 | { 11 | return r * a + (1 - r) * b; 12 | } 13 | \end{lstlisting} 14 | 15 | This is a quite basic function that just combine two values with a 16 | weighted sum. Its implementation tells us that $r$ should probably be 17 | in $[0, 1]$, but most importantly, the computation makes sense only if 18 | T is a float-like type. If we want to prevent the compiler or the 19 | programmer to call this function with an incompatible type, we can add 20 | some SFINAE\footnote{Substitution Failure Is Not An Error, is a 21 | principle in template instantiations according to which the compiler 22 | must not emit an error if it fails to instantiate a 23 | template. Instead it should try another template candidate. This 24 | feature is often used and abused to provide multiple implementation 25 | behind the same function signature.}, for example by introducing a 26 | type deduced from T that would not be defined if T is not a float-like 27 | type. In \cpp98 the implementation could have been similar to: 28 | 29 | \lstinputlistinghl{21}{examples/type-traits/mix-98.hpp} 30 | 31 | Aside from the fact that \code{long double} is not handled, does it 32 | work as expected? 33 | 34 | \begin{lstlisting} 35 | void test() 36 | { 37 | // float and double are handled as expected. 38 | printf("%f\n", mix(1.f, 3.f, 0.5f)); 39 | printf("%f\n", mix(1.d, 3.d, 0.5d)); 40 | 41 | // Using integers triggers an error, we can say that it fails successfully! 42 | // printf("%d\n", mix(1, 3, 2)); 43 | } 44 | \end{lstlisting} 45 | 46 | Typing custom type like \code{only\_if\_float\_like} for every use 47 | case is repetitive, so we would certainly end up splitting it into two 48 | types, that could be used like 49 | \code{only\_if::value, T>::type}. 50 | 51 | \solutiontitle 52 | 53 | \marginheader{}% 54 | % 55 | Lucky us, \cpp11 greatly simplify this work by introducing the 56 | required types, in the form of \code{std::enable\_if} and 57 | \code{std::is\_floating\_point\_type}. Using these types the whole 58 | implementation is reduced to the following: 59 | 60 | \lstinputlistinghl{4}{examples/type-traits/mix-11.hpp} 61 | 62 | There are many other predicates and operations added in 63 | \cppheader{type\_traits} in \cpp11, that can greatly help for 64 | metaprogramming. I can only suggest to have a look at them on a nice 65 | online reference. 66 | -------------------------------------------------------------------------------- /parts/11/uniform-initialization.tex: -------------------------------------------------------------------------------- 1 | \subsection{Uniform initialization} 2 | \label{uniform-initialization} 3 | 4 | \problemtitle 5 | 6 | There are so many ways to initialize a variable in \cpp{} that it 7 | became a running gag, so it's natural that a new initialization syntax 8 | was added into \cpp11. 9 | 10 | Anyway, let's jump to the problem. The following code is a recurring 11 | issue in \cpp{}, so much that even experienced programmers stumble 12 | upon it once in a while. 13 | 14 | \begin{lstlisting} 15 | struct foo {}; 16 | 17 | struct bar 18 | { 19 | bar(foo f); 20 | 21 | int i; 22 | }; 23 | 24 | int main() 25 | { 26 | bar foobar(foo()); 27 | printf("%d\n", foobar.i); 28 | 29 | return 0; 30 | } 31 | \end{lstlisting} 32 | 33 | The question is ``what is \code{foobar} in the above code?'' Most 34 | \cpp{} programmers will say it is a \code{bar} constructed with a 35 | default-constructed \code{foo}. Unfortunately it is actually the 36 | declaration of a function returning \code{bar} and taking a function 37 | returning a \code{foo} as its single argument. This problem is known 38 | as \emph{the most vexing parse}. 39 | 40 | A workaround for this issue is to declare a temporary of type 41 | \code{foo} and pass it to the constructor of \code{bar}: 42 | 43 | \begin{lstlisting} 44 | int main() 45 | { 46 | foo f; 47 | bar foobar(f); 48 | printf("%d\n", foobar.i); 49 | } 50 | \end{lstlisting} 51 | 52 | This is not very convenient, and suddenly the scope is polluted by a 53 | useless variable. Moreover it can quickly become hard to implement 54 | when a variable number of arguments are passed to \code{foobar} 55 | (e.g. by forwarding the arguments of a variadic macro, or a variadic 56 | template \ref{variadic-template}). 57 | 58 | \solutiontitle 59 | 60 | Enters the uniform initialization from \cpp11. By replacing the 61 | parentheses with brackets in the construction of the argument, the 62 | ambiguity is lifted. 63 | 64 | \begin{lstlisting} 65 | int main() 66 | { 67 | bar foobar(foo{}); 68 | printf("%d\n", foobar.i); 69 | } 70 | \end{lstlisting} 71 | 72 | Used like that, the brackets mean something like ``a default-created 73 | \code{foo}''. It can also be used to zero-initialize any variable, 74 | which is especially nice in a template context: 75 | 76 | \begin{lstlisting} 77 | template 78 | void many_tees() 79 | { 80 | // If T is a class, calls the default constructor. 81 | // If T is a fundamental type (e.g. int), its value is 82 | // whatever is in memory at &t1. 83 | T t1; 84 | 85 | // Declares a function t2 with no argument and returning 86 | // a T. 87 | T t2(); 88 | 89 | // Seems to work. Does it? 90 | T t3 = T(); 91 | 92 | // If T is a class, calls the default constructor. 93 | // If T is a fundamental type (e.g. int), its value is 94 | // the zero of this type. 95 | T t4{}; 96 | } 97 | \end{lstlisting} 98 | 99 | \subsubsection{When to Use the Uniform Initialization Syntax} 100 | 101 | Consider the code below: 102 | 103 | \lstinputlistinghl{43}{examples/uniform-initialization/struct.cpp} 104 | 105 | What would be the output of this program? The highlighted line 106 | constructs a variant of \code{foo} with what looks like the aggregate 107 | initialization syntax, or is it uniform initialization? Maybe is it a 108 | call to a constructor? Which one? 109 | 110 | Here is the output of this program: 111 | 112 | \begin{lstlisting}[language=bash] 113 | $ a.out 114 | .a=24, .b=42 115 | .a=42, .b=24 116 | .a=24, .b=24 117 | \end{lstlisting} 118 | 119 | So the first call is without surprise an aggregate initialization. 120 | 121 | The second one is a call to the constructor; since there is one 122 | defined for \code{foo\_constructor} then the aggregate initialization 123 | is disabled. Note that before \cpp11 the compiler would have reported 124 | an error, saying that the constructor should be used. Here it calls 125 | the constructor silently even though it looks like an aggregate 126 | initialization. 127 | 128 | The last one is the worst. It creates an \code{std::initializer\_list} 129 | \footnote{See section~\ref{initializer-list} for details about that.} 130 | with the values, then pass it to the corresponding constructor. 131 | 132 | This is painfully ambiguous. Unfortunately, the so-called ``modern'' 133 | \cpp{} programming trend is pushing for using bracket initialization, 134 | maintaining ambiguities everywhere. I prefer to use it 135 | parsimoniously. In particular, uses of \code{std::initializer\_list} 136 | should certainly be avoided as they lure the programmer into thinking 137 | that the assignment is an efficient aggregate initialization while it 138 | is actually copying stuff around. 139 | 140 | \begin{guideline} 141 | Use bracket initialization if: 142 | \begin{itemize} 143 | \item you want to initialize an aggregate, 144 | \item or you want to zero-initialize something in a context where 145 | you don't know for sure what the type of the thing is. 146 | \end{itemize} 147 | 148 | \emph{Do not} use bracket initialization if you want to call a 149 | non-default constructor. 150 | \end{guideline} 151 | 152 | As a side note, the bracket initialization can be used without 153 | specifying the type, for example to assign a variable or for the 154 | return statement of a function: 155 | 156 | \begin{lstlisting} 157 | struct interval 158 | { 159 | interval(); 160 | interval(int a, int b); 161 | }; 162 | 163 | interval build_interval(bool f) 164 | { 165 | interval b; 166 | 167 | if (f) 168 | b = {23, 23}; 169 | 170 | return {42, 32}; 171 | } 172 | \end{lstlisting} 173 | 174 | This is terrible. 175 | 176 | \begin{guideline} 177 | Mind the next reader, write what you mean. 178 | 179 | While the compiler can effortlessly find the type of a variable, or 180 | the type returned by a function, a human will either have to scan 181 | back toward the declarations or be helped by a tool, if they have 182 | one. 183 | 184 | Constructing a value without saying the type is ambiguous for a 185 | human. This is a lot of effort to put on the reader to save some 186 | characters on the writer's side. 187 | 188 | Don't build complex types without explicitly tell what you want to 189 | build. 190 | \end{guideline} 191 | -------------------------------------------------------------------------------- /parts/11/using-parent-function.tex: -------------------------------------------------------------------------------- 1 | \subsection{Using parent functions} 2 | 3 | \problemtitle 4 | 5 | Here is an actual problem I encountered when developing mobile games 6 | in \cpp{}. When targeting Android devices, the application has to do 7 | some calls from the \cpp{} part to the Java part. These calls are done 8 | via the Java Native Interface (JNI), which is accessed via an object 9 | of type \code{JNIEnv}. 10 | 11 | Calling a Java method from Java requires the identifier of the class, 12 | of type \code{jclass}, and the identifier of the method, of type 13 | \code{jmethodID}. When all of them are known, we can call for example 14 | a static method returning an integer as follows: 15 | 16 | \begin{lstlisting} 17 | JNIenv* env = /* … */; 18 | jclass the_class = /* … */; 19 | jmethodID the_method = /* … */; 20 | 21 | const jint result = 22 | env->CallStaticIntMethod(the_class, the_method, /* arguments */); 23 | \end{lstlisting} 24 | 25 | I certainly did not want to write this stuff everywhere and was hoping 26 | for something more like: 27 | 28 | \begin{lstlisting} 29 | // This variable represents the function to call. 30 | static_method method = /* … */; 31 | 32 | // Then we call it like a function. 33 | const jint result = method(/* arguments */); 34 | \end{lstlisting} 35 | 36 | Since all method calls need the same parameters (i.e. the JNI 37 | environment, the class, and the method), I put them in a base class 38 | from which specialization for the returned type would be 39 | created\footnote{This is simplified for the example. Check 40 | \url{https://github.com/IsCoolEntertainment/iscool-core/} for the 41 | actual code.}: 42 | 43 | \begin{lstlisting} 44 | class static_method_base 45 | { 46 | public: 47 | static_method_base 48 | ( JNIEnv* env, jclass class_id, jmethodID method_id ); 49 | 50 | protected: 51 | JNIEnv* m_env; 52 | jclass m_class; 53 | jmethodID m_method; 54 | }; 55 | \end{lstlisting} 56 | 57 | Then I would inherit from this class to create a function object for 58 | each supported return type. Here for a static method returning an 59 | integer: 60 | 61 | \begin{lstlisting} 62 | template< typename R > 63 | class static_method; 64 | 65 | template<> 66 | class static_method: 67 | public static_method_base 68 | { 69 | public: 70 | // This constructor seems useless, doesn't it? 71 | static_method_base 72 | (JNIEnv* env, jclass class_id, jmethodID method_id) 73 | : static_method_base(env, class_id, method_id) 74 | {} 75 | 76 | template 77 | jint operator()(Arg&&... args) const; 78 | }; 79 | \end{lstlisting} 80 | 81 | At this point we have something weird: the only reason we have defined 82 | a constructor in \code{static\_method\textless{}jint\textgreater} is 83 | to be pass its argument to the parent class. Wouldn't it be better if 84 | we could just say ``reuse the constructor from the parent''? 85 | 86 | \solutiontitle 87 | 88 | This is possible thanks to the \code{using} keyword from \cpp11: 89 | 90 | \begin{lstlisting} 91 | template< typename R > 92 | class static_method; 93 | 94 | template<> 95 | class static_method: 96 | public static_method_base 97 | { 98 | public: 99 | // This is concise and precise. 100 | @\emcode{using static\_method\_base::static\_method\_base;}@ 101 | 102 | template 103 | jint operator()(Arg&&... args) const; 104 | }; 105 | \end{lstlisting} 106 | 107 | When used like this, the \code{using} keyword imports the function 108 | into the current class. It is also a way to solve the problem of 109 | parent functions hidden by overloads in the child class: 110 | 111 | \begin{lstlisting} 112 | struct base 113 | { 114 | void foo(); 115 | }; 116 | 117 | struct derived: base 118 | { 119 | // This declaration hides base::foo(). 120 | void foo(int); 121 | }; 122 | 123 | void bar() 124 | { 125 | derived d; 126 | // This fails, derived::foo requires an int argument. 127 | d.foo(); 128 | } 129 | \end{lstlisting} 130 | 131 | With the \code{using} keyword: 132 | 133 | \begin{lstlisting} 134 | struct base 135 | { 136 | void foo(); 137 | }; 138 | 139 | struct derived: base 140 | { 141 | @\emcode{using base::foo;}@ 142 | void foo(int); 143 | }; 144 | 145 | void bar() 146 | { 147 | derived d; 148 | // This is ok, foo is a member function in derived. 149 | d.foo(); 150 | } 151 | \end{lstlisting} 152 | -------------------------------------------------------------------------------- /parts/11/variadic-template.tex: -------------------------------------------------------------------------------- 1 | \subsection{Variadic Templates} 2 | \label{variadic-template} 3 | 4 | \problemtitle 5 | 6 | Let's design a some kind of message dispatcher using features 7 | available before \cpp11. The use case is presented by the code below. 8 | 9 | \lstinputlisting[firstline=3]{examples/variadic-template/main-98.cpp} 10 | 11 | The idea is to have a \code{dispatcher} whose role is to store 12 | functions to be called with arguments provided later. It is 13 | parameterized by the type of the arguments. If we want to accept any 14 | kind of function, we must accept from zero to $n$ arguments. 15 | 16 | A typical solution for that would have been to declare the type with 17 | multiple template parameters and to default these parameters to a type 18 | representing the state of not being used. Then the actual 19 | implementation would have been selected by template specialization of 20 | a super type. In order to keep this example short we are going to 21 | limit our implementation to functions with up to two arguments. 22 | 23 | Here is the dispatcher with the defaulted parameters. 24 | 25 | \lstinputlisting[firstline=7]{examples/variadic-template/dispatcher-98.hpp} 26 | 27 | Let's have a look at the dispatcher implementation with two arguments. 28 | 29 | \lstinputlisting[firstline=7]{examples/variadic-template/dispatcher_impl_2.hpp} 30 | 31 | Nothing special here. Let's look at the implementation with one 32 | argument. 33 | 34 | \lstinputlisting[firstline=7]{examples/variadic-template/dispatcher_impl_1.hpp} 35 | 36 | This is very similar to the previous implementation. We could 37 | factorize some parts (\code{queue()} and \code{m\_scheduled}) by 38 | moving them in a parent class parameterized with 39 | \code{function\_type}, but for now let's just keep it as is. 40 | 41 | The \code{dispatch()} function cannot be factorized though, as its 42 | signature and the \code{m\_scheduled[i](/*args*/)} line is specific to 43 | each version. 44 | 45 | The implementation with no arguments is equivalently similar, so I 46 | won't include it here. I think you got the point: this is a lot of 47 | code, redundant code, for a feature limited to only three use cases 48 | amongst many. Wouldn't it be better if we could put all of that in a 49 | single implementation that would handle any number of arguments? 50 | 51 | \solutiontitle 52 | 53 | The variadic template syntax introduced in \Cpp11 provides a solution 54 | to this problem. 55 | 56 | \lstinputlistinghl[firstline=5]{6}{examples/variadic-template/dispatcher-11.hpp} 57 | 58 | Here we have a single implementation accepting any number of 59 | arguments, and thus covering all use cases from the previous 60 | implementation and more. 61 | 62 | \bigskip 63 | 64 | \label{parameter-pack} 65 | The syntax of \code{typename... Args} defines a \emph{parameter 66 | pack}. This is like a template parameter but with an ellipsis. 67 | 68 | A template with a parameter pack is called a \emph{variadic 69 | template}. Note that it is allowed to mix a parameter pack with 70 | non-pack template arguments, as in \code{template}. 72 | 73 | When an expression containing a parameter pack ends with an ellipsis, 74 | it is replaced by a comma-separated repetition of the same expression 75 | applied to each type from the pack. For example: 76 | 77 | \begin{lstlisting} 78 | template(args_0), 83 | // std::forward(args_1), 84 | // etc); 85 | f(std::forward(args)...); 86 | } 87 | \end{lstlisting} 88 | 89 | Or, for another example, here is a function creating an array of the 90 | names of the types passed as template parameters: 91 | 92 | \begin{lstlisting} 93 | template 94 | void collect_type_names() 95 | { 96 | const char* names[] = {typeid(T).name()...}; 97 | // … 98 | } 99 | \end{lstlisting} 100 | -------------------------------------------------------------------------------- /parts/14.tex: -------------------------------------------------------------------------------- 1 | \chapter{Nice Things from C++14} 2 | 3 | % Changes between C++11 and C++14 4 | % http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1319r0.html 5 | 6 | \Cpp14 is frequently qualified as a bugfix version of \cpp11, indeed 7 | most features are improvements or extensions of things introduced in 8 | the latter. 9 | 10 | Nevertheless, it does not mean that these improvements are not worth 11 | it. Let's see. 12 | 13 | \section{At the Language Level} 14 | \input{parts/14/number-separator} 15 | \input{parts/14/binary-literals} 16 | \input{parts/14/deprecated} 17 | \input{parts/14/generic-lambdas} 18 | \input{parts/14/lambda-capture} 19 | \input{parts/14/return-type-deduction} 20 | \input{parts/14/variable-templates} 21 | \input{parts/14/decltype-auto} 22 | \input{parts/14/relaxed-constexpr} 23 | 24 | % Mergeable allocations are left out as I could not find a compiler 25 | % where this optimization is implemented. 26 | 27 | \section{In the Standard Library} 28 | \input{parts/14/make-unique} 29 | \input{parts/14/integer-sequence} 30 | \input{parts/14/exchange} 31 | \input{parts/14/tuple-addressing-by-type} 32 | 33 | % standard user defined literals 34 | % heterogeneous lookup in associative containers 35 | % enable_if_t (type aliases) 36 | % quoted 37 | -------------------------------------------------------------------------------- /parts/14/binary-literals.tex: -------------------------------------------------------------------------------- 1 | \subsection{Binary Suffix} 2 | 3 | \problemtitle 4 | 5 | In \cpp11 and before, we used to declare bit patterns as hexadecimal 6 | values, or shifts. For example, if one wanted to access the flags 7 | stored in the packed fields from the image descriptor of a GIF 87a 8 | file \cite{gif87a}, the code could have been similar to: 9 | 10 | \begin{lstlisting} 11 | void parse_image_descriptor_fields(std::uint8_t packed_fields) 12 | { 13 | // Bitmask with shifts. 14 | const bool use_local_color_table = packed_fields & (1 << 7); 15 | 16 | // Bitmasks with hexadecimal values. 17 | const bool is_interlaced = packed_fields & 0x40; 18 | const std::int8_t bits_for_color_palette_size_minus_one = 19 | packed_fields & 0x07; 20 | } 21 | \end{lstlisting} 22 | 23 | While not really obscure, this syntax requires some effort from the 24 | reader, and a good understanding of the binary representation of 25 | numbers. What if we could directly write the binary? 26 | 27 | \solutiontitle 28 | 29 | That's possible with \cpp14. Just like the 0x prefix introduces an 30 | hexadecimal value, 0b introduces a binary value: 31 | 32 | \begin{lstlisting} 33 | void parse_image_descriptor_fields(std::uint8_t packed_fields) 34 | { 35 | // Bitmask with binary literal. 36 | const bool use_local_color_table = packed_fields & @\emcode{0b10000000}@; 37 | 38 | // Note that we can use the number separator @\aref{number-separator}@ to split the mask. 39 | const bool is_interlaced = packed_fields & @\emcode{0b0100'0000}@; 40 | const std::int8_t bits_for_color_palette_size_minus_one = 41 | packed_fields & @\emcode{0b0111}@; 42 | } 43 | \end{lstlisting} 44 | -------------------------------------------------------------------------------- /parts/14/decltype-auto.tex: -------------------------------------------------------------------------------- 1 | \subsection{\code{decltype(auto)}} 2 | 3 | \problemtitle 4 | 5 | We saw in \aref{sec:return-type-deduction} that we can now omit the 6 | return type of a function. So can you tell why the assert won't pass 7 | in the code below? 8 | 9 | \begin{lstlisting} 10 | #include 11 | #include 12 | 13 | template 14 | auto invoke(F&& f, Args&&... args) 15 | { 16 | return f(std::forward(args)...); 17 | } 18 | 19 | int& at(int* v, int i) 20 | { 21 | return v[i]; 22 | } 23 | 24 | // Note that no call occurs here since decltype(expression) produces 25 | // the the type at compile-time, _as-if_ the expression was 26 | // evaluated. So it is safe to use nullptr in the arguments. 27 | static_assert 28 | (std::is_same 29 | < 30 | decltype(invoke(&at, nullptr, 42)), 31 | decltype(at(nullptr, 42)) 32 | >::value, 33 | ""); 34 | \end{lstlisting} 35 | 36 | If you ever encounter one of the few use cases where \code{auto} it is 37 | actually useful, you may be surprised that the deduced type does not 38 | match your expectation. In the above code one could read the return 39 | type of \code{invoke} as ``whatever is returned by 40 | \code{f}''. Unfortunately, \code{auto} does not work like that. 41 | 42 | The \code{auto} keyword does not take into account the reference nor 43 | the constness of the expression. That means that the type of 44 | \code{auto\_value} in the code below is actually \code{int}, not 45 | \code{const int\&} like \code{reference}. 46 | 47 | \begin{lstlisting} 48 | #include 49 | 50 | int i; 51 | const int& reference = i; 52 | auto auto_value = reference; 53 | static_assert(std::is_same::value, ""); 54 | \end{lstlisting} 55 | 56 | \solutiontitle 57 | 58 | Most of the time, \code{auto} can be replaced by a more explicit type, 59 | but in the case of the \code{invoke} function the explicit version 60 | requires to repeat the whole body (see 61 | \aref{sec:return-type-deduction}). As a workaround, \cpp14 introduces 62 | the \code{decltype(auto)} specifier, which keeps all the properties of 63 | the type of the statement from which the type is deduced: 64 | 65 | \begin{lstlisting} 66 | #include 67 | #include 68 | 69 | template 70 | @\emcode{decltype(auto)}@ invoke(F&& f, Args&&... args) 71 | { 72 | return f(std::forward(args)...); 73 | } 74 | 75 | int& at(int* v, int i) 76 | { 77 | return v[i]; 78 | } 79 | 80 | // It works! 81 | static_assert 82 | (std::is_same 83 | < 84 | decltype(invoke(&at, nullptr, 42)), 85 | decltype(at(nullptr, 42)) 86 | >::value, 87 | ""); 88 | \end{lstlisting} 89 | 90 | As usual, \code{decltype(auto)} can be used anywhere a type is 91 | required, as long as there is a way for the compiler to deduce the 92 | type. 93 | 94 | As usual, there is no good reason to prefer that when a more explicit 95 | type can be used. 96 | -------------------------------------------------------------------------------- /parts/14/deprecated.tex: -------------------------------------------------------------------------------- 1 | \subsection{\code{[[deprecated]]} Attribute} 2 | 3 | \problemtitle 4 | 5 | As code evolves, some parts naturally become obsolete. Most of the time, 6 | obsolete code can be simply removed, but when it is published as a 7 | public API, great care must be taken in order not to break client 8 | code. 9 | 10 | In such situation, the publisher would typically provide both the old 11 | and the new API for a period of time long enough for the clients to 12 | migrate. Which they may do only if they know which parts are obsolete! 13 | 14 | So the issue here is actually to pass the information to the 15 | developers that the code is going to be deleted. How can we do that? 16 | Maybe by adding a paragraph in the release notes? I've heard that some 17 | people read them. Or maybe a warning in the header? Here we are going 18 | to rely on compiler-specific features, and the warning will be 19 | displayed as soon as the file is included, even if the deprecated code 20 | is not called. What about printing the deprecation message at run 21 | time, when the code is executed\footnote{Please don't.}? 22 | 23 | \solutiontitle 24 | 25 | Starting with \cpp14, the \code{[[deprecated]]} attribute can be used 26 | to target a specific symbol for deprecation, with an explicit message 27 | that will be displayed to the user, if and only if the symbol is used. 28 | 29 | \begin{lstlisting} 30 | [[@\emcode{deprecated}@("Use the button class instead.")]] 31 | class toggle_button 32 | { 33 | /* … */ 34 | }; 35 | 36 | class button 37 | { 38 | public: 39 | [[@\emcode{deprecated}@("Use set_font(const font&) instead.")]] 40 | void set_font(const std::string& font_name); 41 | }; 42 | 43 | void create_buttons() 44 | { 45 | // This line will trigger a deprecation warning. 46 | toggle_button toggle; 47 | 48 | // This one doesn't. 49 | button b; 50 | 51 | // But calling the deprecated method will trigger the warning. 52 | b.set_font("sans"); 53 | } 54 | \end{lstlisting} 55 | 56 | -------------------------------------------------------------------------------- /parts/14/exchange.tex: -------------------------------------------------------------------------------- 1 | \subsection{\code{std::exchange}}% 2 | % 3 | \problemtitle% 4 | % 5 | \marginheader{}% 6 | % 7 | If you are reading this, you certainly had to write a move constructor 8 | at some point. When doing so, the programmer has to ``steal'' the 9 | resources from an instance, and leave the aforementioned instance in a 10 | valid state. In the example from section \ref{sec:move-constructor}, 11 | copied below for convenience, the resource from \code{that} is 12 | transferred to \code{this}, then the field from \code{that} is set to 13 | \code{nullptr}. 14 | 15 | \begin{lstlisting} 16 | struct foo 17 | { 18 | foo(foo&& that) 19 | : m_resource(that.m_resource) 20 | { 21 | that.m_resource = nullptr; 22 | } 23 | }; 24 | \end{lstlisting} 25 | 26 | As a move constructor grows with the number of fields, the distance 27 | between the transfer of the resource in the constructor's initializer 28 | list and the reset in the constructor's body increases. This blurs the 29 | relationship between the two statements, which actually form a single 30 | semantic operation. This is also error-prone, as one may easily forget 31 | one of the two instructions. 32 | 33 | \solutiontitle 34 | 35 | Thankfully \cpp14 introduces a nice small utility with 36 | \code{std::exchange} to solve this issue. 37 | 38 | \begin{lstlisting} 39 | struct foo 40 | { 41 | foo(foo&& that) 42 | // Assign that.m_resource to m_resource and set that.m_resource to 43 | // nullptr, in a single statement. 44 | : m_resource(@\emcode{std::exchange}@(that.m_resource, nullptr)) 45 | {} 46 | }; 47 | \end{lstlisting} 48 | 49 | The \code{std::exchange} function assigns its second parameter to its 50 | first parameter, then returns the previous value of its first 51 | parameter. Yes, there is no actual exchange here… As with 52 | \code{std::move}, the name does not carry the meaning very well, but 53 | at least it solves a problem. 54 | -------------------------------------------------------------------------------- /parts/14/generic-lambdas.tex: -------------------------------------------------------------------------------- 1 | \subsection{Generic Lambdas} 2 | 3 | \problemtitle 4 | 5 | The introduction of lambdas \aref{sec:lambda} in \cpp11 unlocked many 6 | possibilities for the programmer. Despite that, some use cases are 7 | still a bit difficult to tackle. Take for example a unique predicate 8 | that should be applied to two collections of different types, as in 9 | the example below: 10 | 11 | \begin{lstlisting} 12 | #include 13 | #include 14 | 15 | bool same_count_by_sign 16 | (const std::vector& ints, const std::vector& floats) 17 | { 18 | if (ints.size() != floats.size()) 19 | return false; 20 | 21 | const auto non_positive_integer = 22 | [](int v) -> bool 23 | { 24 | return v <= 0; 25 | }; 26 | const auto non_positive_float = 27 | [](float v) -> bool 28 | { 29 | // This is the same body as above. Do I really need two lambdas? 30 | return v <= 0; 31 | }; 32 | 33 | const std::size_t count_ints = 34 | std::count_if(ints.begin(), ints.end(), non_positive_integer); 35 | const std::size_t count_floats = 36 | std::count_if(floats.begin(), floats.end(), non_positive_float); 37 | 38 | return count_ints == count_floats; 39 | } 40 | \end{lstlisting} 41 | 42 | It is a bit disappointing to have two lambdas with the same 43 | body. Intuitively, one would want to templatize it. Unfortunately 44 | template lambdas do not exist, so we have to switch back to the 45 | pre-\cpp11 way with free functions or function objects. 46 | 47 | \begin{lstlisting} 48 | #include 49 | #include 50 | 51 | namespace 52 | { 53 | // There we go, a simple predicate function declared far from its use. 54 | template 55 | bool non_positive(T v) 56 | { 57 | return v <= 0; 58 | } 59 | } 60 | 61 | bool same_count_by_sign 62 | (const std::vector& ints, const std::vector& floats) 63 | { 64 | if (ints.size() != floats.size()) 65 | return false; 66 | 67 | const std::size_t count_ints = 68 | std::count_if(ints.begin(), ints.end(), &non_positive); 69 | const std::size_t count_floats = 70 | std::count_if(floats.begin(), floats.end(), &non_positive); 71 | 72 | return count_ints == count_floats; 73 | } 74 | \end{lstlisting} 75 | 76 | It works, for sure, but it is not what we expect. Moreover, as soon as 77 | a variable has to be captured, we are back to the extremely verbose 78 | functor objects. 79 | 80 | \solutiontitle 81 | 82 | Enters \cpp14 and the generic lambdas. By declaring the lambda's 83 | arguments as \code{auto}, we can declare what is effectively the 84 | equivalent of a template lambda. 85 | 86 | \begin{lstlisting} 87 | #include 88 | #include 89 | 90 | bool same_count_by_sign 91 | (const std::vector& ints, const std::vector& floats) 92 | { 93 | if (ints.size() != floats.size()) 94 | return false; 95 | 96 | const auto non_positive = 97 | [](@\emcode{auto}@ v) -> bool 98 | { 99 | return v <= 0; 100 | }; 101 | 102 | // It's the same predicate in both calls. 103 | const std::size_t count_ints = 104 | std::count_if(ints.begin(), ints.end(), non_positive); 105 | const std::size_t count_floats = 106 | std::count_if(floats.begin(), floats.end(), non_positive); 107 | 108 | return count_ints == count_floats; 109 | } 110 | \end{lstlisting} 111 | 112 | We saw in \ref{sec:lambda} what was the equivalent function object of 113 | a lambda. Here the corresponding transformation, given a lambda 114 | declaration like 115 | 116 | \begin{lstlisting} 117 | [](auto a1, …, auto an ) -> /* return type */ { /* statements */ } 118 | \end{lstlisting} 119 | 120 | would be something like 121 | 122 | \begin{lstlisting} 123 | struct something 124 | { 125 | template 126 | /* return type */ operator()(T1 a1, …, Tn an) const { /* statements */ } 127 | }; 128 | \end{lstlisting} 129 | 130 | Note that the type of the arguments are not related. Each use of 131 | \code{auto} here corresponds to a single template parameter. Also, it 132 | is totally possible to use declare a parameter pack 133 | \aref{variadic-template}, for example by using the \code{auto…} 134 | syntax. 135 | 136 | \begin{guideline} 137 | Mandatory \code{auto}-related notice: mind the next reader; write what 138 | you mean. 139 | 140 | \bigskip 141 | 142 | As usual with the \code{auto} keyword, one may be tempted to use it to 143 | not have to think about the actual needed type, or because it looks 144 | ``generic'' or ``future proof''. Don't do that. 145 | 146 | The \code{auto} keyword is here to tell the compiler and the reader 147 | that the variable can be of many types. If we use it even when a 148 | single type is expected, it loses its meaning, and the code becomes 149 | harder to understand. 150 | \end{guideline} 151 | -------------------------------------------------------------------------------- /parts/14/integer-sequence.tex: -------------------------------------------------------------------------------- 1 | \subsection{Compile-time Integer Sequences}% 2 | \label{sec:integer-sequence} 3 | 4 | \problemtitle 5 | % 6 | \marginheader{}% 7 | % 8 | If you start playing with parameter packs \aref{parameter-pack} and 9 | tuples \aref{sec:tuple}, you will soon encounter a case where you will 10 | need to so something ``for each item in the tuple''. 11 | 12 | A typical use case consists in calling a function with its arguments 13 | taken from a tuple, something we already tried in the previous pages 14 | \aref{example:argument-binding}, in an argument-bindings example. Go 15 | check, and see how much code we wrote to store an sequence of integers 16 | in a type. 17 | 18 | \solutiontitle 19 | 20 | Starting with \cpp14, this code can be replaced by 21 | \code{std::integer\_sequence} and 22 | \code{std::make\_integer\_sequence}. Writing a 23 | function that runs a function with its arguments taken from a tuple is 24 | approximately as simple as this: 25 | 26 | \begin{lstlisting} 27 | // The call_helper will help us to get the elements of a tuple, because we 28 | // cannot get them by type due to possibly duplicate types. 29 | template 30 | struct call_helper; 31 | 32 | template 33 | struct call_helper<@\emcode{std::integer\_sequence}@> 34 | { 35 | template 36 | static void call(F&& function, std::tuple&& arguments) 37 | { 38 | // Here we unpack I... to get the arguments from the tuple. 39 | // See @\aref{variadic-template}@. 40 | // 41 | // Note that it does not work with member functions, as they require another 42 | // call syntax. This is still left as an exercise for the reader. 43 | function(std::get(arguments)...); 44 | } 45 | }; 46 | 47 | template 48 | decltype(auto) apply(F&& function, std::tuple&& arguments) 49 | { 50 | return call_helper 51 | < 52 | @\emcode{std::make\_integer\_sequence}@ 53 | >::call(std::forward(function), std::move(arguments)); 54 | } 55 | \end{lstlisting} 56 | 57 | Isn't it clean? Hold on, we'll soon be able to remove this code too 58 | \aref{sec:apply}\footnote{And it will be for the best, as this example 59 | code misses many features, like calling member functions, accepting 60 | a const tuple as argument, and probably more.}! 61 | -------------------------------------------------------------------------------- /parts/14/lambda-capture.tex: -------------------------------------------------------------------------------- 1 | \subsection{Lambda Capture Expressions} 2 | 3 | \problemtitle 4 | 5 | When we are defining a lambda, we have the possibility to capture 6 | variables of the enclosing scope such that they become available in 7 | the body of the lambda \aref{lambdas-internals}. In practice, such 8 | variables are either copied (like \code{var1} below, due to the 9 | \code{=} syntax), or referenced (like \code{var2} below, with the 10 | \code{\&} syntax). 11 | 12 | \begin{lstlisting} 13 | const auto foo = [=var1, &var2]() -> void {}; 14 | \end{lstlisting} 15 | 16 | Unfortunately there is no other variant of the capture, which leads to 17 | situations like this: 18 | 19 | \begin{lstlisting} 20 | void wait_for_new_players(const std::string& group) 21 | { 22 | std::string display_label = group + ": "; 23 | 24 | // Copies are striking again. Here display_label is copied into a 25 | // field of the function object associated with this lambda; not 26 | // moved nor initialized on construction. 27 | auto add_player_to_list = 28 | [display_label](player_id id, const std::string& player alias) 29 | { 30 | m_player_list->add(id, display_label + alias); 31 | }; 32 | 33 | m_team_service.wait_for_players(group, add_player_to_list); 34 | } 35 | \end{lstlisting} 36 | 37 | In the above example, we would want to avoid the copy of the display 38 | label into the equivalent member variable of the lambda. In \cpp11 39 | there is only two ways to achieve that: either by creating the display 40 | label in the callback's body, thus creating a new string on each 41 | call\footnote{We would also have a copy of the captured group variable 42 | anyway.}, or by using a custom function object, \cpp98-style. 43 | 44 | Additionally, we can note that this behavior prevent any use of a 45 | move-only type for a captured variable, such as 46 | \code{std::unique\_ptr}. Indeed, there is no way to move the variable 47 | from the outer scope into the lambda. 48 | 49 | \solutiontitle 50 | 51 | In \cpp14, capture lists have been extended to allow the initialization 52 | of a variable by an expression. We can use that to initialize the 53 | display label with the final string directly: 54 | 55 | \begin{lstlisting} 56 | void wait_for_new_players(std::string group) 57 | { 58 | // display_label is initialized directly in the construction of the 59 | // lambda, thus saving a copy. 60 | auto add_player_to_list = 61 | [@\emcode{display\_label = group + ": "}@] 62 | (player_id id, const std::string& alias) 63 | { 64 | m_player_list.add(id, display_label + alias); 65 | }; 66 | 67 | m_team_service.wait_for_players(group, add_player_to_list); 68 | } 69 | \end{lstlisting} 70 | 71 | This also solves the move-only type situation since we can now move the 72 | variable: 73 | 74 | \begin{lstlisting} 75 | void apply_filter(std::vector& values, std::unique_ptr filter) 76 | { 77 | std::for_each 78 | (values.begin(), values.end(), 79 | [@\emcode{f = std::move(filter)}@](int& v) -> void 80 | { 81 | v = f->transform(v); 82 | }); 83 | } 84 | \end{lstlisting} 85 | -------------------------------------------------------------------------------- /parts/14/make-unique.tex: -------------------------------------------------------------------------------- 1 | \subsection{\code{make\_unique}} 2 | 3 | \problemtitle 4 | 5 | % 6 | \marginheader{}% 7 | % 8 | \Cpp11 introduced smart pointers in the standard library, with 9 | \code{std::unique\_ptr} and \code{std::shared\_ptr}. For the latter 10 | the idiomatic creation code would use \code{std::make\_shared}, which 11 | would have the benefit to create storage for the control block and the 12 | actual object into a single allocation. On the other hand, 13 | \code{std::unique\_ptr} has no control block, so it made sense at the 14 | time not to have specialized creation functions for it. 15 | 16 | There is another use case though, where such function can help: 17 | 18 | \begin{lstlisting} 19 | create_form 20 | (std::unique_ptr(new label("Everything is fine.")), 21 | std::unique_ptr(new icon("resources/alert.png"))); 22 | \end{lstlisting} 23 | 24 | See, since there is no guarantee on the order of evaluation of 25 | function arguments, the compiler is free to sequence them as follows: 26 | 27 | \begin{enumerate} 28 | \item \code{new label(…)} 29 | \item \code{new icon(…)} 30 | \item \code{std::unique\_ptr(…)} 31 | \item \code{std::unique\_ptr(…)} 32 | \end{enumerate} 33 | 34 | Now, if the constructor of \code{icon} throws an exception, then the 35 | \code{label} won't ever be destroyed, nor its memory released during 36 | the program execution. 37 | 38 | \solutiontitle 39 | 40 | This can be solved by wrapping the allocation in a function, a 41 | function provided by the standard library for example. 42 | 43 | \begin{lstlisting} 44 | create_form 45 | (std::make_unique