diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 653195b..e672ba2 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -1015,10 +1015,10 @@ Time and space that you spend well to achieve a goal (e.g., speed of development X waste(const char* p) { - if (p == nullptr) throw Nullptr_error{}; + if (!p) throw Nullptr_error{}; int n = strlen(p); auto buf = new char[n]; - if (buf == nullptr) throw Allocation_error{}; + if (!buf) throw Allocation_error{}; for (int i = 0; i < n; ++i) buf[i] = p[i]; // ... manipulate buffer ... X x; @@ -1499,7 +1499,7 @@ Ideally, that `Expects(x >= 0)` should be part of the interface of `sqrt()` but ##### Note -Prefer a formal specification of requirements, such as `Expects(p != nullptr);`. +Prefer a formal specification of requirements, such as `Expects(p);`. If that is infeasible, use English text in comments, such as `// the sequence [p:q) is ordered using <`. ##### Note @@ -3214,7 +3214,7 @@ Consider: int length(Record* p); -When I call `length(p)` should I test for `p == nullptr` first? Should the implementation of `length()` test for `p == nullptr`? +When I call `length(p)` should I check if `p` is `nullptr` first? Should the implementation of `length()` check if `p` is `nullptr`? // it is the caller's job to make sure p != nullptr int length(not_null p); @@ -3301,7 +3301,7 @@ Consider: int length(const char* p); -When I call `length(s)` should I test for `s == nullptr` first? Should the implementation of `length()` test for `p == nullptr`? +When I call `length(s)` should I check if `s` is `nullptr` first? Should the implementation of `length()` check if `p` is `nullptr`? // the implementor of length() must assume that p == nullptr is possible int length(zstring p); @@ -3389,7 +3389,7 @@ Sometimes having `nullptr` as an alternative to indicated "no object" is useful, string zstring_to_string(zstring p) // zstring is a char*; that is a C-style string { - if (p == nullptr) return string{}; // p might be nullptr; remember to check + if (!p) return string{}; // p might be nullptr; remember to check return string{p}; } @@ -3422,7 +3422,7 @@ Returning a `T*` to transfer ownership is a misuse. Node* find(Node* t, const string& s) // find s in a binary tree of Nodes { - if (t == nullptr || t->name == s) return t; + if (!t || t->name == s) return t; if ((auto p = find(t->left, s))) return p; if ((auto p = find(t->right, s))) return p; return nullptr; @@ -5022,7 +5022,7 @@ Leaving behind an invalid object is asking for trouble. X2(const string& name) :f{fopen(name.c_str(), "r")} { - if (f == nullptr) throw runtime_error{"could not open" + name}; + if (!f) throw runtime_error{"could not open" + name}; // ... } @@ -10649,7 +10649,7 @@ Requires messy cast-and-macro-laden code to get working right. for (;;) { // treat the next var as a char*; no checking: a cast in disguise char* p = va_arg(ap, char*); - if (p == nullptr) break; + if (!p) break; cerr << p << ' '; } @@ -11872,7 +11872,7 @@ There are many approaches to dealing with this potential problem: void f1(int* p) // deal with nullptr { - if (p == nullptr) { + if (!p) { // deal with nullptr (allocate, return, throw, make p point to something, whatever } int x = *p; @@ -11887,7 +11887,7 @@ There are two potential problems with testing for `nullptr`: void f2(int* p) // state that p is not supposed to be nullptr { - assert(p != nullptr); + assert(p); int x = *p; } @@ -11895,7 +11895,7 @@ This would carry a cost only when the assertion checking was enabled and would g This would work even better if/when C++ gets direct support for contracts: void f3(int* p) // state that p is not supposed to be nullptr - [[expects: p != nullptr]] + [[expects: p]] { int x = *p; } @@ -15453,7 +15453,7 @@ In such cases, "crashing" is simply leaving error handling to the next level of { // ... p = static_cast(malloc(n, X)); - if (p == nullptr) abort(); // abort if memory is exhausted + if (!p) abort(); // abort if memory is exhausted // ... } @@ -19440,7 +19440,7 @@ Of course many simple functions will naturally have just one `return` because of int index(const char* p) { - if (p == nullptr) return -1; // error indicator: alternatively "throw nullptr_error{}" + if (!p) return -1; // error indicator: alternatively "throw nullptr_error{}" // ... do a lookup to find the index for p return i; } @@ -19450,7 +19450,7 @@ If we applied the rule, we'd get something like int index2(const char* p) { int i; - if (p == nullptr) + if (!p) i = -1; // error indicator else { // ... do a lookup to find the index for p @@ -20033,7 +20033,7 @@ Use `not_null` for C-style strings that cannot be `nullptr`. ??? Do we These assertions are currently macros (yuck!) and must appear in function definitions (only) pending standard committee decisions on contracts and assertion syntax. See [the contract proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0380r1.pdf); using the attribute syntax, -for example, `Expects(p != nullptr)` will become `[[expects: p != nullptr]]`. +for example, `Expects(p)` will become `[[expects: p]]`. ## GSL.util: Utilities