C++17 - The Complete Guide: Errata of First Edition |
This is the errata of the 1st printing of the
book C++17 - The Complete
Guide by Nicolai
M. Josuttis.
It covers all errors that were found.
The errata is organized in
the following way:
- The first part lists technical errors
- The second part lists typos
Usually the latest electronic version covers all issues of this errata.
Page 34, 4.2 Using Extended Aggregate Initialization: 2019-12-20
Replace:
by:
Page 43, 5.3.1, Value Categories Since C++11: 2020-09-26
A few examples for value categories should be clarified:
Examples of lvalues are:
- An expression that is just the name of a variable, function, or data member (except a plain value member of an rvalue)
- ...
- Any reference to a function, even when marked with std::move()
...
Examples of xvalues are:
- ...
- A non-static value member of an rvalue
Page 102, 10.2.2 Other Compile-Time if Examples: Compile-Time if for Tag Dispatching
A typename is missing twice (before
C++20).
Twice replace:
using cat = std::iterator_traits<Iterator>::iterator_category;
by
using cat = typename std::iterator_traits<Iterator>::iterator_category;
Page 143, 15.2.2 std::optional<> Operations: Comnparisons: 2019-12-20
Replace:
If both operands are objects without a value, they are considered to be equal (== yields true and all other comparisons yield false).
by:
If both operands
are objects without a value, they are considered to be equal (==,
<=, and >= yield true
and all other comparisons yield false).
Page 176, 17.2.2 Any Operations, Changing the Value: 2019-10-08
Replace:
by:a.emplace{std::in_place_type<std::string>, "hello"};
// a contains value of type std::string
a.emplace{std::in_place_type<std::complex<double>>, 4.4, 5.5};
// a contains value of type std::complex<double>
a.emplace<std::string>("hello");
// a contains value of type std::string
a.emplace<std::complex<double>>(4.4, 5.5);
// a contains value of type std::complex<double>
Page 196, 19.4.2, String View Operations: Modifying a String View: 2020-09-25
You have to convert all string views to be able to call + for them.
Replace:
by:One of the operands has to be a string:
auto s2 = std::string(sv1) + sv2; // OK
Both of the operands have to be strings:
auto s2 = std::string(sv1) + std::string(sv2); // OK
Page 202, 20.1.1,checkpath2.cpp: 2019-08-29
All output of path p should use p.string().
Page 238, 20.4.4 Filesystem Modifications: Table 20.15. Creating and Deleting Files: 2019-12-20
Replace:
create_hard_link(old, new) | Creates another filesystem entry to for the existing file from
by:
create_hard_link(to, new) | Creates another filesystem entry new for the existing file to
Page 316, 26.3, Container-Support of Incomplete Types: 2019-10-08
The link to http://drdobbs.com/184403814 is gone. Instead, you can use: http://web.archive.org/web/20190305220304/http://www.drdobbs.com/184403814
Page xvii, Acknowledgments
s/ Thomas, Köppe / Thomas Köppe /
Page 18, 1.3 Enable Structured Bindings with Write Access:
s/return std::move(c.firstname();) }/return std::move(c.firstname()); }/
Page 33, Chapter 4 Aggregate Extensions
s/ you no longer need te equal sign / you no longer need the equal sign /
Page 63, 8.2 Defined Expression Evaluation Order
s/ e1.f is guaranteed to be evaluated before a1, a2, and a3 now. / e1 is guaranteed to be evaluated before a1, a2, and a3 now. /
Page 65, 8.2 Defined Expression Evaluation Order, right before 8.3:
s/ "value " / "value: " / (twice)
Page 68, 8.6 UTF-8 Character Literals:
s/ u6'6'/ u8'6' /
Page 73: 8.9 Preprocessor Condition __has_include
s/ if (__has_include(<filesystem>) / if (__has_include(<filesystem>)) /
Page 78, 9.1 Use of Class Template Argument Deduction
s/ class tuple; / class tuple { /
Page 79, 9.1.1 Coyping by Default:
s/ std::vector v2{v1}; // v2 also is vector<int> / std::vector v2{v1}; // v2 also is vector<int> /
s/ std::vector vv{v, v}; // vv is vector<vector<int>> / std::vector vv{v1, v2}; // vv is vector<vector<int>> /
Page 85, 9.2.1 Using Deduction Guides to Force Decay
s/ we pass type const char(&)[6] so that T is deduced as const char[6]: / we pass type const char(&)[6] so that T is deduced as char[6]: /
Page 113, 11.2.2 Supported Operators
s/ void callFoo(const Types&... args) / void callFoo(Types&&... args) /
Page 114, 11.2.2 Supported Operators
s/ (hashCombine(seed,"World")),hashCombine(seed,42)) / hashCombine(seed,"World")),hashCombine(seed,42) /
Page 114, 11.2.2 Supported Operators
s/ to use it as an unordered set / to use it in an unordered set /
Page 177, 11.2.3 Using Fold Expressions for Types
s/ std::is_same_v<int,MyType> / std::is_same_v<int,Size> /
Page 136, 15.1.1 Optional Return Values
s/ The program asInt() contains a function / The program contains a function asInt() /
s/ signaling that we don not have / signaling that we do not have /
Page 140, 15.2.2 std::optional<> Operations: Construction
s/ provided the underlying supports copying / provided their underlying type supports copying /
Page 143, 15.2.2 std::optional<> Operations: Accessing the Value
s/ meaning that the contained is not copy constructed / meaning that the contained value is not copy constructed /
Page 151, 16.2 Using std::variant<>: std::monostate
s/ Their own purpose / Their only purpose /
Page 155, 16.3.2 std::variant<> Operations
s/ For std::variant<>, You / For std::variant<>, you /
Page 167: 16.4.2 Other Heterogeneous Collections with std::variant
A closing } is missing in the last code example.
Page 168, 16.4.3, Comparing variant Polymorphism:
s/ which approach is faster for you On different platforms, / which approach is faster for your code. On different platforms, /
Page 175, 17.2.2 Any Operations: Construction
s/ // a2 contains value of type const char* / // a3 contains value of type const char* /
Page 183, 18.2.2 std::byte Operations: I/O with std::byte
s/ if (! std::cin.fail()) { / if (! strm.fail()) { /
Page 198, 19.5.1 Using String Views instead of Strings
At the end of the section, the first example call of sort() should also have the std::execution::par argument.
Page 205, 20.1.2 Switch Over Filesystem Type: Namespace fs
s/ as s shortcut / as a shortcut /
Page 226, 20.3.5 Path Modifications: Table 20.7
s/ p.concat(sub) / p.concat(str) /
Page 234, 20.4.2 File Status: Table 20.12
Remove p at the end of the symlink_status(p) effect
Page 244, 20.4.6 Other Filesystem Operations
s/ auto currentDir{std::filesystem::current_path(); / auto currentDir{std::filesystem::current_path()}; /
Page 260, 22.1.1, lib/parforeach.cpp: Table 22.3
s / // initialize NumElems values without square root: / // initialize numElems values without square root: /
Page 267, 22.5 Overview of Parallel Algorithms
s/ copy_backward() move_backward() / copy_backward(), move_backward() /
Page 274, 22.6 Motivation for New Algorithms for Parallel Processing: Parallelization for Non-Associative Operations
s/ 1; 2 or 3 / 1, 2, or 3 /
Page 277, 22.6.1, transform_reduce() for Filesystemn Operations
s/ given as command-line arguments / given as command-line argument /
Page 283, 285: 23.2.2 std::transform_reduce()
s/ InputIterator beg, InputIterator end) / InputIterator beg, InputIterator end, /
Page 286, 23.2.2, lib/transform_reduce2.cpp:
s / // process sum of differences of squared elements: / // process sum (concatenation) of concatenated digits: /
Page 287, 289: 23.2.3 std::inclusive_scan() and std::exclusive_scan()
s/ InputIterator
beg, InputIterator end) / InputIterator beg, InputIterator end, /
s/ T initVal) / T initVal, /
s/ BinaryOp op, / BinaryOp op) /
s / std::exclusive_scan / std::exclusive_scan() /
s/ and write them to the soure starting with / and write them to the destination range starting with /
Page 289: 23.2.4 std::transform_inclusive_scan() and std::transform_exclusive_scan()
s/ InputIterator
beg, InputIterator end) / InputIterator beg, InputIterator end, /
s/ T initVal) / T initVal, /
s/ BinaryOp op, / BinaryOp op) /
Page 294, 24.1.1, Using Searchers with search()
s/ To use this searchers / To use these searchers /
Page 296, 24.2, Using General Subsequence Searchers
s/ std::cout << "found subsequence at << " beg - coll.begin() << '\n'; / std::cout << "found subsequence at " << beg - coll.begin() << '\n'; /
Page 297, 24.3, Using Searcher Predicates
s/ searches / seachers / (twice)
Page 298, 24.4, Afternotes
s/ These searches / The seachers /
Page 300, 25.1.1 Generic size() function
s/ last5 / printLast5 / (twice)
Page 301, 25.1.2, Generic empty() Function, Footnote:
s/ However, using std::size() for such an empty C array does not compile. / However, using std::empty() for such an empty C array does not compile. /
Page 311, 26.1. Node Handles
s/ By introducing the ability to splice node / By introducing the ability to splice a node /
Page 316, 26.3.3 try_emplace()
s/ The is no definition of whether/ There is no definition of whether /
Page 332, 28.3.1
s/ lcm(x, x) / lcm(x, y)
Page 332, 28.3.1 Greatest common divisor and least common multiple
s/ returning / returns / (twice)
Page 332, 28.3.2 3-Argument Overloads of std::hypot()
s/ returning / returns /
Page 355, 29.2 Defining Custom Memory Resources
In pmr/tracker.hpp the second constructor should initialize the members in the opposite order to avoid warnings:
s/ : prefix{std::move(p)}, upstream{us} { / : upstream{us}, prefix{std::move(p)} { /
Page 358, 29.2.1 Equality of Memory Resources
The code of do_is_equal() should again check for an equal upstream as done before.
Page 370, 30.2.1 Implementing Aligned Allocation Before C++17
in comment: s/ of, if none exists / or if none exists /
Page 375: 30.2.2 Implementing Type-Specific operator new(): When Is operator new() Called?
After the return in operator new remove: ::operator delete(p);
Page 377,
s/ ::operator delete(p2, std::align_val_t{64}); // !!! / ::operator delete(p1, std::align_val_t{64}); // !!! /
s/ MyType32::operator delete(p1, std::align_val_t{64}); // !!! / MyType32::operator delete(p2, std::align_val_t{64}); // !!! /
Page 383, 30.4. Tracking all ::new Calls
s/ I this example / In this example /
Page 401, 33.1 std::invoke<>():
s/ call(printT / call(print / (twice)
Page 412, 35.2.7, Deprecated Library Features:
s/ codecvt> / <codecvt> /