std::ceil was replaced by std::floor + 1. In this way, the algorithm works also for edge cases of 0 and 1. (p.24/4)
Approximation of e
To demonstrate the workings of views::partial_sum, the original Maclaurin expansion has been replaced by an adjusted factorial expansion, namely:
e ~ 1/1! + 2/2! + 3/3! + 4/4!...
This allows us to use views::iota, views::partial_sum and views::zip_with. (p.24)
Luhn algorithm
A note was added about how to deal with credit cards with an odd number of digits.
Prepend 0 for this scenario using e.g. views::concat(views::single(0),...). (p.27)
Palindrome
Only half of the original range and half of the reversed range are now used for the final comparison, as this is a sufficient condition
to determine palindromic behavior. (p.30)
Area of a polygon
A note was added on the assumptions of the solution, namely a non-intersecting polygon with a clockwise vertex order. (p.31)
Range comprehensions - Pythagorean triples
Euclid's solution which uses the generators m and n was improved to account for opposite parity (m odd, n even or vice versa) and coprimality, i.e. the greatest common divisors of m and n is 1. This approach allows to exclude the multiples of primitive solutions, such as [6,8,10]. (p.45)
Range-v3 comprehensions - Squarions
The check i != j highlighted below was removed as the same can be achieved by modifying the upper bound from views::iota(1,i+1)
to views::iota(1,i). (p.46)
Keys now represent positions of elements (not values). As a result, views::zip(v, views::iota(0)) has been replaced by v | views::enumerate.
Note that we now explicitly require an unsigned type for the input vector. (p.53)
Range-v3-related changes
Seven bridges of Konigsberg and Matrix operations
views::all was removed from the example of Seven bridges of Konigsberg and Matrix operations, as this was only used to resolve
a temporary issue related to arrays and Concepts. (p.32/2,37)
int const m [3][3] = {{1,2,3},{4,5,6},{7,8,9}};
// auto r = m | views::all | views::join; // [1,2,3,4,5,6,7,8,9]
auto r = m | views::join; // [1,2,3,4,5,6,7,8,9]
Quick reference
views::common and views::ref were added to the Quick reference. (p.68/X1,X2)
C++-related changes
Undefined behavior
Undefined behavior was discovered in the usage of yield_if in the examples of Molecular weight and Planetary masses.
The issue was related to std::optional that would have been dereferenced regardless of whether it contained a value or not.
While the original code compiled fine under CLANG, this was a case of undefined behavior. (p.41/6,43/7)
return yield_if(w.has_value(),*w); // undefined behavior
return yield_if(w.has_value(), w.value_or(0.0)); // ok
char was changed to unsigned char in cases where std::isdigit, std::isalnum, std::tolower and std::isspace was used as part of a lambda expression (p.19,29,30,35,42,66). E.g.
return s | views::remove_if([](char c){
return std::isspace(c);}) // incorrect
return s | views::remove_if([](unsigned char c){
return std::isspace(c);}) // ok
Other changes
std::stringstream was globally replaced by std::istringstream.
The keyword static was added to the example Chunk consecutive vowels in the Practice section (p.52).
Digits in regular expressions were unified under [0-9] instead of \\d. (p.40)
An explicit conversion to int was added to determine whether a square root is an integer number in Range comprehensions - Squarions. (p.46)
Acknowledgement
A special thank you goes to Szilárd Szalóki for his comments on the 2nd edition.