diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md
index f71c716..68bba56 100644
--- a/CppCoreGuidelines.md
+++ b/CppCoreGuidelines.md
@@ -1,6 +1,6 @@
# C++ Core Guidelines
-April 4, 2017
+April 9, 2017
Editors:
@@ -9770,19 +9770,16 @@ For containers, there is a tradition for using `{...}` for a list of elements an
##### Note
-Initialization of a variable declared using `auto` with a single value, e.g., `{v}`, had surprising results until recently:
+Initialization of a variable declared using `auto` with a single value, e.g., `{v}`, had surprising results until C++17.
+The C++17 rules are somewhat less surprising:
auto x1 {7}; // x1 is an int with the value 7
- // x2 is an initializer_list with an element 7
- // (this will will change to "element 7" in C++17)
- auto x2 = {7};
+ auto x2 = {7}; // x2 is an initializer_list with an element 7
auto x11 {7, 8}; // error: two initializers
auto x22 = {7, 8}; // x2 is an initializer_list with elements 7 and 8
-##### Exception
-
-Use `={...}` if you really want an `initializer_list`
+So use `={...}` if you really want an `initializer_list`
auto fib10 = {0, 1, 2, 3, 5, 8, 13, 21, 34, 55}; // fib10 is a list
@@ -9826,12 +9823,16 @@ increases readability, and it has zero or near zero runtime cost.
{
auto p1 = make_unique(7); // OK
int* p2 = new int{7}; // bad: might leak
- // ...
+ // ... no assignment to p2 ...
if (leak) return;
+ // ... no assignment to p2 ...
+ vector v(7);
+ v.at(7) = 0; // exception thrown
// ...
}
If `leak == true` the object pointed to by `p2` is leaked and the object pointed to by `p1` is not.
+The same is the case when `at()` throws.
##### Enforcement
@@ -10373,6 +10374,7 @@ consider `gsl::finally()` as a cleaner and more reliable alternative to `goto ex
##### Reason
In a non-trivial loop body, it is easy to overlook a `break` or a `continue`.
+
A `break` in a loop has a dramatically different meaning than a `break` in a `switch`-statement
(and you can have `switch`-statement in a loop and a loop in a `switch`-case).
@@ -10861,11 +10863,29 @@ Flag uses of `0` and `NULL` for pointers. The transformation may be helped by si
##### Reason
-Casts are a well-known source of errors. Makes some optimizations unreliable.
+Casts are a well-known source of errors. Make some optimizations unreliable.
-##### Example
+##### Example, bad
- ???
+ double d = 2;
+ auto p = (long*)&d;
+ auto q = (long long*)&d;
+ cout << d << ' ' << *p << ' ' << *q << '\n';
+
+What would you think this fragment prints? The result is at best implementation defined. I got
+
+ 2 0 4611686018427387904
+
+Adding
+
+ *q = 666;
+ cout << d << ' ' << *p << ' ' << *q << '\n';
+
+I got
+
+ 3.29048e-321 666 666
+
+Surprised? I'm just glad I didn't crash the program.
##### Note
@@ -10910,15 +10930,29 @@ The named casts are:
##### Example
- ???
+ class B { /* ... */ };
+ class D { /* ... */ };
+
+ template D* upcast(B* pb)
+ {
+ D* pd0 = pb; // error: no implicit conversion from B* to D*
+ D* pd1 = (D*)pb; // legal, but what is done?
+ D* pd2 = static_cast(pb); // error: D is not derived from B
+ D* pd3 = reinterpret_cast(pb); // OK: on your head be it!
+ D* pd4 = dynamic_cast(pb); // OK: return nullptr
+ // ...
+ }
+
+The example was synthesized from real-world bugs where `D` used to be derived from `B`, but someone refactored the hierarchy.
+The C-style cast is dangerous because it can do any kind of conversion, depriving us of any protection from mistakes (now or in the future).
##### Note
When converting between types with no information loss (e.g. from `float` to
`double` or `int64` from `int32`), brace initialization may be used instead.
- double d{some_float};
- int64_t i{some_int32};
+ double d {some_float};
+ int64_t i {some_int32};
This makes it clear that the type conversion was intended and also prevents
conversions between types that might result in loss of precision. (It is a