diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md
index d34928b..c27fe7f 100644
--- a/CppCoreGuidelines.md
+++ b/CppCoreGuidelines.md
@@ -4,7 +4,7 @@ layout: default
# C++ Core Guidelines
-September 18, 2017
+October 5, 2017
Editors:
@@ -12,7 +12,7 @@ Editors:
* [Bjarne Stroustrup](http://www.stroustrup.com)
* [Herb Sutter](http://herbsutter.com/)
-This document is a very early draft. It is inkorrekt, incompleat, and pµÃoorly formatted.
+This document is an early draft. It's known to be incomplet, incorrekt, and has lots of b**a**d **fo**rm~att~ing.
Had it been an open-source (code) project, this would have been release 0.8.
Copying, use, modification, and creation of derivative works from this project is licensed under an MIT-style license.
Contributing to this project requires agreeing to a Contributor License. See the accompanying [LICENSE](LICENSE) file for details.
@@ -1203,7 +1203,7 @@ Interface rule summary:
* [I.8: Prefer `Ensures()` for expressing postconditions](#Ri-ensures)
* [I.9: If an interface is a template, document its parameters using concepts](#Ri-concepts)
* [I.10: Use exceptions to signal a failure to perform a required task](#Ri-except)
-* [I.11: Never transfer ownership by a raw pointer (`T*`)](#Ri-raw)
+* [I.11: Never transfer ownership by a raw pointer (`T*`) or reference (`T&`)](#Ri-raw)
* [I.12: Declare a pointer that must not be null as `not_null`](#Ri-nullptr)
* [I.13: Do not pass an array as a single pointer](#Ri-array)
* [I.22: Avoid complex initialization of global objects](#Ri-global-init)
@@ -1776,7 +1776,7 @@ We don't consider "performance" a valid reason not to use exceptions.
* (Not enforceable) This is a philosophical guideline that is infeasible to check directly.
* Look for `errno`.
-### I.11: Never transfer ownership by a raw pointer (`T*`)
+### I.11: Never transfer ownership by a raw pointer (`T*`) or reference (`T&`)
##### Reason
@@ -4395,7 +4395,6 @@ Destructor rules:
* [C.31: All resources acquired by a class must be released by the class's destructor](#Rc-dtor-release)
* [C.32: If a class has a raw pointer (`T*`) or reference (`T&`), consider whether it might be owning](#Rc-dtor-ptr)
* [C.33: If a class has an owning pointer member, define or `=delete` a destructor](#Rc-dtor-ptr2)
-* [C.34: If a class has an owning reference member, define or `=delete` a destructor](#Rc-dtor-ref)
* [C.35: A base class with a virtual function needs a virtual destructor](#Rc-dtor-virtual)
* [C.36: A destructor may not fail](#Rc-dtor-fail)
* [C.37: Make destructors `noexcept`](#Rc-dtor-noexcept)
@@ -4770,63 +4769,6 @@ That would sometimes require non-trivial code changes and may affect ABIs.
* A class with a pointer data member is suspect.
* A class with an `owner` should define its default operations.
-### C.34: If a class has an owning reference member, define a destructor
-
-##### Reason
-
-A reference member may represent a resource.
-It should not do so, but in older code, that's common.
-See [pointer members and destructors](#Rc-dtor-ptr).
-Also, copying may lead to slicing.
-
-##### Example, bad
-
- class Handle { // Very suspect
- Shape& s; // use reference rather than pointer to prevent rebinding
- // BAD: vague about ownership of *p
- // ...
- public:
- Handle(Shape& ss) : s{ss} { /* ... */ }
- // ...
- };
-
-The problem of whether `Handle` is responsible for the destruction of its `Shape` is the same as for [the pointer case](#Rc-dtor-ptr):
-If the `Handle` owns the object referred to by `s` it must have a destructor.
-
-##### Example
-
- class Handle { // OK
- owner s; // use reference rather than pointer to prevent rebinding
- // ...
- public:
- Handle(Shape& ss) : s{ss} { /* ... */ }
- ~Handle() { delete &s; }
- // ...
- };
-
-Independently of whether `Handle` owns its `Shape`, we must consider the default copy operations suspect:
-
- // the Handle had better own the Circle or we have a leak
- Handle x {*new Circle{p1, 17}};
-
- Handle y {*new Triangle{p1, p2, p3}};
- x = y; // the default assignment will try *x.s = *y.s
-
-That `x = y` is highly suspect.
-Assigning a `Triangle` to a `Circle`?
-Unless `Shape` has its [copy assignment `=deleted`](#Rc-copy-virtual), only the `Shape` part of `Triangle` is copied into the `Circle`.
-
-##### Note
-
-Why not just require all owning references to be replaced by "smart pointers"?
-Changing from references to smart pointers implies code changes.
-We don't (yet) have smart references.
-Also, that may affect ABIs.
-
-##### Enforcement
-
-* A class with a reference data member is suspect.
-* A class with an `owner` reference should define its default operations.
### C.35: A base class destructor should be either public and virtual, or protected and nonvirtual
@@ -6851,7 +6793,7 @@ First we devise a hierarchy of interface classes:
class Circle : public Shape { // pure interface
public:
- int radius() = 0;
+ virtual int radius() = 0;
// ...
};
@@ -6861,13 +6803,13 @@ To make this interface useful, we must provide its implementation classes (here,
public:
// constructors, destructor
// ...
- virtual Point center() const { /* ... */ }
- virtual Color color() const { /* ... */ }
+ Point center() const override { /* ... */ }
+ Color color() const override { /* ... */ }
- virtual void rotate(int) { /* ... */ }
- virtual void move(Point p) { /* ... */ }
+ void rotate(int) override { /* ... */ }
+ void move(Point p) override { /* ... */ }
- virtual void redraw() { /* ... */ }
+ void redraw() override { /* ... */ }
// ...
};
@@ -6879,7 +6821,7 @@ but bear with us because this is just a simple example of a technique aimed at m
public:
// constructors, destructor
- int radius() { /* ... */ }
+ int radius() override { /* ... */ }
// ...
};
@@ -7915,6 +7857,45 @@ Note that `std::addressof()` always yields a built-in pointer.
Tricky. Warn if `&` is user-defined without also defining `->` for the result type.
+### C.167: Use an operator for an operation with its conventional meaning
+
+##### Reason
+
+Readability. Convention. Reusability. Support for generic code
+
+##### Example
+
+ void cout_my_class(const My_class& c) // confusing, not conventional,not generic
+ {
+ std::cout << /* class members here */;
+ }
+
+ std::ostream& operator<<(std::ostream& os, const my_class& c) // OK
+ {
+ return os << /* class members here */;
+ }
+
+By itself, `cout_my_class` would be OK, but it is not usable/composable with code that rely on the `<<` convention for output:
+
+ My_class var { /* ... */ };
+ // ...
+ cout << "var = " << var << '\n';
+
+##### Note
+
+There are strong and vigorous conventions for the meaning most operators, such as
+
+* comparisons (`==`, `!=`, `<`, `<=`, `>`, and `>=`),
+* arithmetic operations (`+`, `-`, `*`, `/`, and `%`)
+* access operations (`.`, `->`, unary `*`, and `[]`)
+* assignment (`=`)
+
+Don't define those unconventionally and don't invent your own names for them.
+
+##### Enforcement
+
+Tricky. Requires semantic insight.
+
### C.168: Define overloaded operators in the namespace of their operands
##### Reason
@@ -7980,45 +7961,6 @@ This is a special case of the rule that [helper functions should be defined in t
* Flag operator definitions that are not it the namespace of their operands
-### C.167: Use an operator for an operation with its conventional meaning
-
-##### Reason
-
-Readability. Convention. Reusability. Support for generic code
-
-##### Example
-
- void cout_my_class(const My_class& c) // confusing, not conventional,not generic
- {
- std::cout << /* class members here */;
- }
-
- std::ostream& operator<<(std::ostream& os, const my_class& c) // OK
- {
- return os << /* class members here */;
- }
-
-By itself, `cout_my_class` would be OK, but it is not usable/composable with code that rely on the `<<` convention for output:
-
- My_class var { /* ... */ };
- // ...
- cout << "var = " << var << '\n';
-
-##### Note
-
-There are strong and vigorous conventions for the meaning most operators, such as
-
-* comparisons (`==`, `!=`, `<`, `<=`, `>`, and `>=`),
-* arithmetic operations (`+`, `-`, `*`, `/`, and `%`)
-* access operations (`.`, `->`, unary `*`, and `[]`)
-* assignment (`=`)
-
-Don't define those unconventionally and don't invent your own names for them.
-
-##### Enforcement
-
-Tricky. Requires semantic insight.
-
### C.170: If you feel like overloading a lambda, use a generic lambda
##### Reason
@@ -10170,7 +10112,7 @@ Many such errors are introduced during maintenance years after the initial imple
##### Exception
-It you are declaring an object that is just about to be initialized from input, initializing it would cause a double initialization.
+If you are declaring an object that is just about to be initialized from input, initializing it would cause a double initialization.
However, beware that this may leave uninitialized data beyond the input -- and that has been a fertile source of errors and security breaches:
constexpr int max = 8 * 1024;
@@ -11229,12 +11171,13 @@ Helps make style consistent and conventional.
By definition, a condition in an `if`-statement, `while`-statement, or a `for`-statement selects between `true` and `false`.
A numeric value is compared to `0` and a pointer value to `nullptr`.
- if (p) { ... } // means "if `p` is not `nullptr`, good
- if (p!=0) { ... } // means "if `p` is not `nullptr`, redundant `!=0`; bad: don't use 0 for pointers
- if (p!=nullptr) { ... } // means "if `p` is not `nullptr`, redundant `!=nullptr`, not recommended
+ // These all mean "if `p` is not `nullptr`"
+ if (p) { ... } // good
+ if (p != 0) { ... } // redundant `!=0`; bad: don't use 0 for pointers
+ if (p != nullptr) { ... } // redundant `!=nullptr`, not recommended
Often, `if (p)` is read as "if `p` is valid" which is a direct expression of the programmers intent,
-whereas `if (p!=nullptr)` would be a long-winded workaround.
+whereas `if (p != nullptr)` would be a long-winded workaround.
##### Example
@@ -11242,14 +11185,14 @@ This rule is especially useful when a declaration is used as a condition
if (auto pc = dynamic_cast(ps)) { ... } // execute is ps points to a kind of Circle, good
- if (auto pc = dynamic_cast(ps); pc!=nullptr) { ... } // not recommended
+ if (auto pc = dynamic_cast(ps); pc != nullptr) { ... } // not recommended
##### Example
Note that implicit conversions to bool are applied in conditions.
For example:
- for (string s; cin>>s; ) v.push_back(s);
+ for (string s; cin >> s; ) v.push_back(s);
This invokes `istream`'s `operator bool()`.
@@ -11257,13 +11200,13 @@ This invokes `istream`'s `operator bool()`.
It has been noted that
- if(strcmp(p1,p2)) { ... } // are the two C-style strings equal? (mistake!)
+ if(strcmp(p1, p2)) { ... } // are the two C-style strings equal? (mistake!)
is a common beginners error.
If you use C-style strings, you must know the `` functions well.
Being verbose and writing
- if(strcmp(p1,p2)!=0) { ... } // are the two C-style strings equal? (mistake!)
+ if(strcmp(p1, p2) != 0) { ... } // are the two C-style strings equal? (mistake!)
would not save you.
@@ -11271,9 +11214,10 @@ would not save you.
The opposite condition is most easily expressed using a negation:
- if (!p) { ... } // means "if `p` is`nullptr`, good
- if (p==0) { ... } // means "if `p` is `nullptr`, redundant `!=0`; bad: don't use `0` for pointers
- if (p==nullptr) { ... } // means "if `p` is `nullptr`, redundant `==nullptr`, not recommended
+ // These all mean "if `p` is `nullptr`"
+ if (!p) { ... } // good
+ if (p == 0) { ... } // redundant `!= 0`; bad: don't use `0` for pointers
+ if (p == nullptr) { ... } // redundant `== nullptr`, not recommended
##### Enforcement
@@ -11692,7 +11636,7 @@ A key example is basic narrowing:
##### Note
-The guideline support library offers a `narrow` operation for specifying that narrowing is acceptable and a `narrow` ("narrow if") that throws an exception if a narrowing would throw away information:
+The guideline support library offers a `narrow_cast` operation for specifying that narrowing is acceptable and a `narrow` ("narrow if") that throws an exception if a narrowing would throw away information:
i = narrow_cast(d); // OK (you asked for it): narrowing: i becomes 7
i = narrow(d); // OK: throws narrowing_error
@@ -19844,7 +19788,7 @@ These types allow the user to distinguish between owning and non-owning pointers
These "views" are never owners.
-References are never owners. Note: References have many opportunities to outlive the objects they refer to (returning a local variable by reference, holding a reference to an element of a vector and doing `push_back`, binding to `std::max(x, y + 1)`, etc. The Lifetime safety profile aims to address those things, but even so `owner` does not make sense and is discouraged.
+References are never owners (see [R.4](#Rr-ref). Note: References have many opportunities to outlive the objects they refer to (returning a local variable by reference, holding a reference to an element of a vector and doing `push_back`, binding to `std::max(x, y + 1)`, etc. The Lifetime safety profile aims to address those things, but even so `owner` does not make sense and is discouraged.
The names are mostly ISO standard-library style (lower case and underscore):