diff --git a/01-string-and-character-literals.md b/01-string-and-character-literals.md index 23ac3c6..904de69 100644 --- a/01-string-and-character-literals.md +++ b/01-string-and-character-literals.md @@ -1,4 +1,4 @@ -# String and Character Literals +# String and Character Literals ## Introducing a Modern C++ program @@ -133,7 +133,7 @@ While little hands make vain pretence Our wanderings to guide. ``` -* Now use a (non-raw) string literal for each line and a single call to `print()` with suitable escape characters. What happens if you remove all of the stream insertion operators *except* for the first? (Explanation: *concatenation* of adjacent string literals is automatically performed by the pre-processor.) +* Now use a (non-raw) string literal for each line and a single call to `print()` with suitable escape characters. You concatenate the string literals without any operator: *concatenation* of adjacent string literals is automatically performed by the pre-processor. * Modify `01-title.cpp` to output the title of your favorite book or film centered on the console window (assume an 80 character fixed width, and change the size of the console window if different). @@ -156,7 +156,7 @@ The following table lists C++ types, sizes, target encodings, literals and objec | char32_t | 32 | UTF-32 | U"abcd" | U'a' | UR"(abcd)" | u32string | n/a | no | | wchar_t | 16/32 | n/a + | L"abcd" | L'a' | LR"(abcd)" | wstring | wcout/wcerr | no | -* An explicit cast to type `char` in `operator<<` may be required when using `cout`/`cerr`, for example: `cout << static_cast(u8"Hello \u20AC!\n");`. +* An explicit cast to type `char` in `operator<<` may be required when using `cout`/`cerr`, for example: `cout << reinterpret_cast(u8"Hello \u20AC!\n");`. + The `wchar_t` encoding and streams under Windows are 16-bit and support UTF-16. diff --git a/02-variables-scopes-and-namespaces.md b/02-variables-scopes-and-namespaces.md index e28ef63..732db2b 100644 --- a/02-variables-scopes-and-namespaces.md +++ b/02-variables-scopes-and-namespaces.md @@ -1,4 +1,4 @@ -# Variables, Scopes and Namespaces +# Variables, Scopes and Namespaces ## Declarations, definitions and assignment @@ -468,6 +468,9 @@ In fact, `constexpr` expressions can be complex with recent compilers, as long a #include using namespace std; +// Note: currently, not all compilers mark `acos` as a +// constexpr function in cmath. The following line might +// not compile with `clang++` for example. constexpr double PI1 = acos(-1.0); constexpr double PI2 = 22.0 / 7.0; @@ -480,7 +483,7 @@ int main() { } ``` -(Hint: this program is the first to require an additional header to ``; you may need to add `-lm` to the compile command under Linux/MacOS in order to link in the math library containing the `acos()` function.) +(Hint: this program is the first to require an additional header to ``; you may need to add `-lm` to the compile command under Linux in order to link in the math library containing the `acos()` function.) **Experiment** diff --git a/03-conditions-and-operators.md b/03-conditions-and-operators.md index 7148b19..d8e77ae 100644 --- a/03-conditions-and-operators.md +++ b/03-conditions-and-operators.md @@ -1,4 +1,4 @@ -# Conditions and Operators +# Conditions and Operators ## Run-time user input diff --git a/04-functions.md b/04-functions.md index d81e754..fad23eb 100644 --- a/04-functions.md +++ b/04-functions.md @@ -1,4 +1,4 @@ -# Functions +# Functions ## Scopes @@ -538,7 +538,7 @@ The keyword `noexcept` is used to declare that a function is guaranteed to not t #include using namespace std; -void throw_if_zero(int i) { +void throw_if_zero(int i) noexcept { if (!i) { throw runtime_error("found a zero"); } diff --git a/07-strings-containers-and-views.md b/07-strings-containers-and-views.md index 516aa9f..b8fcfd5 100644 --- a/07-strings-containers-and-views.md +++ b/07-strings-containers-and-views.md @@ -394,11 +394,11 @@ vector: 1 9 7 3 set: 3 4 6 8 Found in string at position: 2 Found in vector: 7 -Found in set: 4 +Found in set: 6 After: string: helo vector: 1 9 3 -set: 3 6 8 +set: 3 4 8 ``` Take time to study this program as it contains some important concepts: @@ -693,15 +693,17 @@ There are some other containers and *container adaptors* implemented in the Stan * `std::bitset` also stores binary bits, but has its size fixed at compile-time -* `std::deque` (pronounced "deck") implements a double-ended FIFO similar to `std::vector` +* `std::deque` (pronounced "deck") implements a double-ended container similar to `std::vector`, but with additional operations such as `push_front()` -* `std::stack` implements a LIFO +* `std::stack` implements a LIFO (Last In First Out) -* `std::queue` implements a FIFO +* `std::queue` implements a FIFO (First In First Out) * `std::priority_queue` implements a FIFO that sorts by age and priority -* `std::flat_map` implements an unordered map essentially as two vectors +* `std::flat_set` implements a sorted container of unique values, typically implemented as a vector + +* `std::flat_map` implements a sorted associative container, typically implemented as two vectors (one for keys and one for values) A brief Tutorial such as this is not the place to delve into these, and indeed the other containers covered in this Chapter have much more detail to discover. As a go-to for both tutorial and reference I can highly recommend [CppReference.com](https://en.cppreference.com)[^1] and [Josuttis, "The C++ Standard Library"](http://cppstdlib.com)[^2]. diff --git a/08-files-and-formatting.md b/08-files-and-formatting.md index 35eb974..39b2125 100644 --- a/08-files-and-formatting.md +++ b/08-files-and-formatting.md @@ -1,4 +1,4 @@ -# Files and Formatting +# Files and Formatting ## Formatting values and variables for output diff --git a/10-templates-exceptions-lambdas-smart-pointers.md b/10-templates-exceptions-lambdas-smart-pointers.md index 2174547..721eb10 100644 --- a/10-templates-exceptions-lambdas-smart-pointers.md +++ b/10-templates-exceptions-lambdas-smart-pointers.md @@ -372,8 +372,7 @@ struct MinMaxAvg { int main() { vector v{ 3, 5, 2, 6, 2, 4 }; - MinMaxAvg f; - for_each(begin(v), end(v), ref(f)); + MinMaxAvg f = for_each(begin(v), end(v), MinMaxAvg{}); cout << "Min: " << f.min << " Max: " << f.max << " Avg: " << f.avg << " Num: " << f.num << '\n'; } @@ -381,13 +380,11 @@ int main() { A few points to note about this program: -* Only `num` and `first` are required to be set before the first `std::for_each()` call; we have used universal initializtion of the member variables, but this could also be achieved by using a (default-)constructor. +* Only `num` and `first` are required to be set before the `std::for_each()` call; we have used universal initialization of the member variables, but this could also be achieved by using a (default-)constructor. -* The definition of `f` (a `MinMaxAvg` function object) is required **before** the call to `std::for_each()` so that its state is still accessible after the call. It is destroyed at the end of `main()`, as this is the scope it is declared within. The code `for_each(begin(v), end(v), MinMaxAvg{});` would compile, but its result would be lost as the functor would itself be destroyed here. +* The assignment of `f` (a `MinMaxAvg` function object) is the result of the call to `std::for_each()`, being the modified (default-constructed) third parameter. -* The syntax `std::ref(f)` passes the function object by reference, with plain `f` a **copy** would be made which would mean the copy's member variables would be discarded at the end of the `for_each()` scope, so again the result would be lost. - -* The function template `std::for_each()` call decomposes to the equivalent of: `f(3); f(5); f(2); f(6); f(2); f(4);`. Of course, a range-for loop could be used to accomplish the same thing, but the *logic* would have to be written (or repeated) within the body of the loop. +* The function template `std::for_each()` call decomposes to the equivalent of: `auto f = MinMaxAvg{}; f(3); f(5); f(2); f(6); f(2); f(4);`. Of course, a range-for loop could be used to accomplish the same thing, but the *logic* within the functor's `operator()` would have to be written (or repeated) within the body of the loop. **Experiment:** diff --git a/headers/02-constexpr.cpp b/headers/02-constexpr.cpp index 511551b..4e478c7 100644 --- a/headers/02-constexpr.cpp +++ b/headers/02-constexpr.cpp @@ -4,6 +4,9 @@ #include using namespace std; +// Note: currently, not all compilers mark `acos` as a +// constexpr function in cmath. The following line might +// not compile with `clang++` for example. constexpr double PI1 = acos(-1.0); constexpr double PI2 = 22.0 / 7.0; diff --git a/headers/04-noexcept.cpp b/headers/04-noexcept.cpp index 7c07a63..5ac841f 100644 --- a/headers/04-noexcept.cpp +++ b/headers/04-noexcept.cpp @@ -4,7 +4,7 @@ #include using namespace std; -int throw_if_zero(int i) noexcept { +void throw_if_zero(int i) noexcept { if (!i) { throw runtime_error("found a zero"); } @@ -12,13 +12,13 @@ int throw_if_zero(int i) noexcept { } int main() { - cout << "Entering main()\n"; + println("Entering main()"); try { throw_if_zero(1); throw_if_zero(0); } - catch(...) { - println("Caught an exception!"); + catch(exception& e) { + println("Caught an exception: {}", e.what()); } - println("Leaving main()\n"); + println("Leaving main()"); } diff --git a/headers/10-functor2.cpp b/headers/10-functor2.cpp index 353a2ce..81ec9ce 100644 --- a/headers/10-functor2.cpp +++ b/headers/10-functor2.cpp @@ -28,8 +28,7 @@ struct MinMaxAvg { int main() { vector v{ 3, 5, 2, 6, 2, 4 }; - MinMaxAvg f; - for_each(begin(v), end(v), ref(f)); + MinMaxAvg f = for_each(begin(v), end(v), MinMaxAvg{}); cout << "Min: " << f.min << " Max: " << f.max << " Avg: " << f.avg << " Num: " << f.num << '\n'; } diff --git a/modules/02-constexpr.cpp b/modules/02-constexpr.cpp index a394d45..6e138c1 100644 --- a/modules/02-constexpr.cpp +++ b/modules/02-constexpr.cpp @@ -3,6 +3,9 @@ import std; using namespace std; +// Note: currently, not all compilers mark `acos` as a +// constexpr function in cmath. The following line might +// not compile with `clang++` for example. constexpr double PI1 = acos(-1.0); constexpr double PI2 = 22.0 / 7.0; diff --git a/modules/04-noexcept.cpp b/modules/04-noexcept.cpp index 7f56f15..dec1d95 100644 --- a/modules/04-noexcept.cpp +++ b/modules/04-noexcept.cpp @@ -3,7 +3,7 @@ import std; using namespace std; -int throw_if_zero(int i) noexcept { +void throw_if_zero(int i) noexcept { if (!i) { throw runtime_error("found a zero"); } @@ -11,13 +11,13 @@ int throw_if_zero(int i) noexcept { } int main() { - cout << "Entering main()\n"; + println("Entering main()"); try { throw_if_zero(1); throw_if_zero(0); } - catch(...) { - println("Caught an exception!"); + catch(exception& e) { + println("Caught an exception: {}", e.what()); } - println("Leaving main()\n"); + println("Leaving main()"); } diff --git a/modules/10-functor2.cpp b/modules/10-functor2.cpp index 48cec8d..fd468e1 100644 --- a/modules/10-functor2.cpp +++ b/modules/10-functor2.cpp @@ -26,8 +26,7 @@ struct MinMaxAvg { int main() { vector v{ 3, 5, 2, 6, 2, 4 }; - MinMaxAvg f; - for_each(begin(v), end(v), ref(f)); + MinMaxAvg f = for_each(begin(v), end(v), MinMaxAvg{}); cout << "Min: " << f.min << " Max: " << f.max << " Avg: " << f.avg << " Num: " << f.num << '\n'; }