Merge pull request #696 from tkruse/style-fixes

Style fixes
This commit is contained in:
Gabriel Dos Reis
2016-09-06 01:14:20 -07:00
committed by GitHub

View File

@@ -3142,10 +3142,10 @@ Here on one popular implementation I got the output:
I expected that because the call of `g()` reuses the stack space abandoned by the call of `f()` so `*p` refers to the space now occupied by `gx`. I expected that because the call of `g()` reuses the stack space abandoned by the call of `f()` so `*p` refers to the space now occupied by `gx`.
Imagine what would happen if `fx` and `gx` were of different types. * Imagine what would happen if `fx` and `gx` were of different types.
Imagine what would happen if `fx` or `gx` was a type with an invariant. * Imagine what would happen if `fx` or `gx` was a type with an invariant.
Imagine what would happen if more that dangling pointer was passed around among a larger set of functions. * Imagine what would happen if more that dangling pointer was passed around among a larger set of functions.
Imagine what a cracker could do with that dangling pointer. * Imagine what a cracker could do with that dangling pointer.
Fortunately, most (all?) modern compilers catch and warn against this simple case. Fortunately, most (all?) modern compilers catch and warn against this simple case.
@@ -3400,7 +3400,7 @@ There is not a choice when a set of functions are used to do a semantically equi
##### See also ##### See also
[Default arguments for virtual functions](#Rh-virtual-default-arg} [Default arguments for virtual functions](#Rh-virtual-default-arg)
##### Enforcement ##### Enforcement
@@ -7368,7 +7368,7 @@ Wrap a `union` in a class together with a type field.
The soon-to-be-standard `variant` type (to be found in `<variant>`) does that for you: The soon-to-be-standard `variant` type (to be found in `<variant>`) does that for you:
variant<int,double> v; variant<int, double> v;
v = 123; // v holds an int v = 123; // v holds an int
int x = get<int>(v); int x = get<int>(v);
v = 123.456; // v holds a double v = 123.456; // v holds a double
@@ -7420,19 +7420,19 @@ Saving programmers from having to write such code is one reason for including `v
int Value::number() const int Value::number() const
{ {
if (type!=Tag::number) throw Bad_entry{}; if (type != Tag::number) throw Bad_entry{};
return i; return i;
} }
string Value::text() const string Value::text() const
{ {
if (type!=Tag::text) throw Bad_entry{}; if (type != Tag::text) throw Bad_entry{};
return s; return s;
} }
void Value::set_number(int n) void Value::set_number(int n)
{ {
if (type==Tag::text) { if (type == Tag::text) {
s.~string(); // explicitly destroy string s.~string(); // explicitly destroy string
type = Tag::number; type = Tag::number;
} }
@@ -7441,7 +7441,7 @@ Saving programmers from having to write such code is one reason for including `v
void Value::set_text(const string& ss) void Value::set_text(const string& ss)
{ {
if (type==Tag::text) if (type == Tag::text)
s = ss; s = ss;
else { else {
new(&s) string{ss}; // placement new: explicitly construct string new(&s) string{ss}; // placement new: explicitly construct string
@@ -7451,12 +7451,12 @@ Saving programmers from having to write such code is one reason for including `v
Value& Value::operator=(const Value& e) // necessary because of the string variant Value& Value::operator=(const Value& e) // necessary because of the string variant
{ {
if (type==Tag::text && e.type==Tag::text) { if (type == Tag::text && e.type == Tag::text) {
s = e.s; // usual string assignment s = e.s; // usual string assignment
return *this; return *this;
} }
if (type==Tag::text) s.~string(); // explicit destroy if (type == Tag::text) s.~string(); // explicit destroy
switch (e.type) { switch (e.type) {
case Tag::number: case Tag::number:
@@ -7472,7 +7472,7 @@ Saving programmers from having to write such code is one reason for including `v
Value::~Value() Value::~Value()
{ {
if (type==Tag::text) s.~string(); // explicit destroy if (type == Tag::text) s.~string(); // explicit destroy
} }
##### Enforcement ##### Enforcement
@@ -8460,14 +8460,14 @@ Any type (including primary template or specialization) that overloads unary `*`
##### Example ##### Example
// use Boost's intrusive_ptr // use Boost's intrusive_ptr
#include <boost/intrusive_ptr.hpp> #include<boost/intrusive_ptr.hpp>
void f(boost::intrusive_ptr<widget> p) // error under rule 'sharedptrparam' void f(boost::intrusive_ptr<widget> p) // error under rule 'sharedptrparam'
{ {
p->foo(); p->foo();
} }
// use Microsoft's CComPtr // use Microsoft's CComPtr
#include <atlbase.h> #include<atlbase.h>
void f(CComPtr<widget> p) // error under rule 'sharedptrparam' void f(CComPtr<widget> p) // error under rule 'sharedptrparam'
{ {
p->foo(); p->foo();
@@ -9168,7 +9168,7 @@ Reuse of a member name as a local variable can also be a problem:
void S::f(int x) void S::f(int x)
{ {
m=7; // assign to member m = 7; // assign to member
if (x) { if (x) {
int m = 9; int m = 9;
// ... // ...
@@ -9487,7 +9487,9 @@ For containers, there is a tradition for using `{...}` for a list of elements an
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 recently:
auto x1 {7}; // x1 is an int with the value 7 auto x1 {7}; // x1 is an int with the value 7
auto x2 = {7}; // x2 is an initializer_list<int> with an element 7 (this will will change to "element 7" in C++17) // x2 is an initializer_list<int> with an element 7
// (this will will change to "element 7" in C++17)
auto x2 = {7};
auto x11 {7, 8}; // error: two initializers auto x11 {7, 8}; // error: two initializers
auto x22 = {7, 8}; // x2 is an initializer_list<int> with elements 7 and 8 auto x22 = {7, 8}; // x2 is an initializer_list<int> with elements 7 and 8
@@ -9776,7 +9778,7 @@ Requires messy cast-and-macro-laden code to get working right.
##### Example ##### Example
#include <cstdarg> #include<cstdarg>
// "severity" followed by a zero-terminated list of char*s; write the C-style strings to cerr // "severity" followed by a zero-terminated list of char*s; write the C-style strings to cerr
void error(int severity ...) void error(int severity ...)
@@ -10364,7 +10366,7 @@ A key example is basic narrowing:
double d = 7.9; double d = 7.9;
int i = d; // bad: narrowing: i becomes 7 int i = d; // bad: narrowing: i becomes 7
i = (int)d; // bad: we're going to claim this is still not explicit enough i = (int) d; // bad: we're going to claim this is still not explicit enough
void f(int x, long y, double d) void f(int x, long y, double d)
{ {
@@ -10511,7 +10513,7 @@ Consider keeping previously computed results around for a costly operation:
class Cache { // some type implementing a cache for an int->int operation class Cache { // some type implementing a cache for an int->int operation
public: public:
pair<bool,int> find(int x) const; // is there a value for x? pair<bool, int> find(int x) const; // is there a value for x?
void set(int x, int v); // make y the value for x void set(int x, int v); // make y the value for x
// ... // ...
private: private:
@@ -10525,7 +10527,7 @@ Consider keeping previously computed results around for a costly operation:
auto p = cache.find(x); auto p = cache.find(x);
if (p.first) return p.second; if (p.first) return p.second;
int val = compute(x); int val = compute(x);
cache.set(x,val); // insert value for x cache.set(x, val); // insert value for x
return val; return val;
} }
// ... // ...
@@ -10543,7 +10545,7 @@ To do this we still need to mutate `cache`, so people sometimes resort to a `con
auto p = cache.find(x); auto p = cache.find(x);
if (p.first) return p.second; if (p.first) return p.second;
int val = compute(x); int val = compute(x);
const_cast<Cache&>(cache).set(x,val); // ugly const_cast<Cache&>(cache).set(x, val); // ugly
return val; return val;
} }
// ... // ...
@@ -10561,7 +10563,7 @@ State that `cache` is mutable even for a `const` object:
auto p = cache.find(x); auto p = cache.find(x);
if (p.first) return p.second; if (p.first) return p.second;
int val = compute(x); int val = compute(x);
cache.set(x,val); cache.set(x, val);
return val; return val;
} }
// ... // ...
@@ -10939,12 +10941,15 @@ The build-in array uses signed types for subscripts.
This makes surprises (and bugs) inevitable. This makes surprises (and bugs) inevitable.
int a[10]; int a[10];
for (int i=0; i<10; ++i) a[i]=i; for (int i=0; i < 10; ++i) a[i]=i;
vector<int> v(10); vector<int> v(10);
for (int i=0; v.size()<10; ++i) v[i]=i; // compares signed to unsigned; some compilers warn // compares signed to unsigned; some compilers warn
for (int i=0; v.size() < 10; ++i) v[i]=i;
int a2[-2]; // error: negative size int a2[-2]; // error: negative size
vector<int> v2(-2); // OK, but the number of ints (4294967294) is so large that we should get an exception
// OK, but the number of ints (4294967294) is so large that we should get an exception
vector<int> v2(-2);
##### Enforcement ##### Enforcement
@@ -11190,7 +11195,7 @@ Because a design that ignore the possibility of later improvement is hard to cha
From the C (and C++) standard: From the C (and C++) standard:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*)); void qsort (void* base, size_t num, size_t size, int (*compar)(const void*, const void*));
When did you even want to sort memory? When did you even want to sort memory?
Really, we sort sequences of elements, typically stored in containers. Really, we sort sequences of elements, typically stored in containers.
@@ -11200,7 +11205,10 @@ This implies added work for the programmer, is error prone, and deprives the com
double data[100]; double data[100];
// ... fill a ... // ... fill a ...
qsort(data,100,sizeof(double),compare_doubles); // 100 chunks of memory of sizeof(double) starting at address data using the order defined by compare_doubles
// 100 chunks of memory of sizeof(double) starting at
// address data using the order defined by compare_doubles
qsort(data, 100, sizeof(double), compare_doubles);
From the point of view of interface design is that `qsort` throws away useful information. From the point of view of interface design is that `qsort` throws away useful information.
@@ -11209,13 +11217,15 @@ We can do better (in C++98)
template<typename Iter> template<typename Iter>
void sort(Iter b, Iter e); // sort [b:e) void sort(Iter b, Iter e); // sort [b:e)
sort(data,data+100); sort(data, data + 100);
Here, we use the compiler's knowledge about the size of the array, the type of elements, and how to compare `double`s. Here, we use the compiler's knowledge about the size of the array, the type of elements, and how to compare `double`s.
With C++11 plus [concepts](#???), we can do better still With C++11 plus [concepts](#???), we can do better still
void sort(Sortable& c); // Sortable specifies that c must be a random-access sequence of elements comparable with < // Sortable specifies that c must be a
// random-access sequence of elements comparable with <
void sort(Sortable& c);
sort(c); sort(c);
@@ -11224,7 +11234,8 @@ In this, the `sort` interfaces shown here still have a weakness:
They implicitly rely on the element type having less-than (`<`) defined. They implicitly rely on the element type having less-than (`<`) defined.
To complete the interface, we need a second version that accepts a comparison criteria: To complete the interface, we need a second version that accepts a comparison criteria:
void sort(Sortable& c, Predicate<Value_type<Sortable>> p); // compare elements of c using p // compare elements of c using p
void sort(Sortable& c, Predicate<Value_type<Sortable>> p);
The standard-library specification of `sort` offers those two versions, The standard-library specification of `sort` offers those two versions,
but the semantics is expressed in English rather than code using concepts. but the semantics is expressed in English rather than code using concepts.
@@ -11267,7 +11278,7 @@ Don't let bad designs "bleed into" your code.
Consider: Consider:
template <class ForwardIterator, class T> template <class ForwardIterator, class T>
bool binary_search (ForwardIterator first, ForwardIterator last, const T& val); bool binary_search(ForwardIterator first, ForwardIterator last, const T& val);
`binary_search(begin(c),end(c),7)` will tell you whether `7` is in `c` or not. `binary_search(begin(c),end(c),7)` will tell you whether `7` is in `c` or not.
However, it will not tell you where that `7` is or whether there are more than one `7`. However, it will not tell you where that `7` is or whether there are more than one `7`.
@@ -11283,13 +11294,13 @@ needed information back to the caller. Therefore, the standard library also offe
However, `lower_bound` still doesn't return enough information for all uses, so the standard library also offers However, `lower_bound` still doesn't return enough information for all uses, so the standard library also offers
template <class ForwardIterator, class T> template <class ForwardIterator, class T>
pair<ForwardIterator,ForwardIterator> pair<ForwardIterator, ForwardIterator>
equal_range (ForwardIterator first, ForwardIterator last, const T& val); equal_range(ForwardIterator first, ForwardIterator last, const T& val);
`equal_range` returns a `pair` of iterators specifying the first and one beyond last match. `equal_range` returns a `pair` of iterators specifying the first and one beyond last match.
auto r = equal_range(begin(c),end(c),7); auto r = equal_range(begin(c), end(c),7);
for (auto p = r.first(); p!=r.second(), ++p) for (auto p = r.first(); p != r.second(), ++p)
cout << *p << '\n'; cout << *p << '\n';
Obviously, these three interfaces are implemented by the same basic code. Obviously, these three interfaces are implemented by the same basic code.
@@ -12069,7 +12080,7 @@ A `thread` that has not been `detach()`ed when it is destroyed terminates the pr
##### Enforcement ##### Enforcement
* Flag `join's for `raii_thread`s ??? * Flag `join`s for `raii_thread`s ???
* Flag `detach`s for `detached_thread`s * Flag `detach`s for `detached_thread`s
@@ -13957,7 +13968,7 @@ It also avoids brittle or inefficient workarounds. Convention: That's the way th
}; };
Container c(10, sizeof(double)); Container c(10, sizeof(double));
((double*)c.elem)[] = 9.9; ((double*) c.elem)[] = 9.9;
This doesn't directly express the intent of the programmer and hides the structure of the program from the type system and optimizer. This doesn't directly express the intent of the programmer and hides the structure of the program from the type system and optimizer.
@@ -15458,7 +15469,7 @@ Variadic templates is the most general mechanism for that, and is both efficient
##### Enforcement ##### Enforcement
* Flag uses of `va_arg` in user code. * Flag uses of `va_arg` in user code.
### <a name="Rt-variadic-pass"></a>T.101: ??? How to pass arguments to a variadic template ??? ### <a name="Rt-variadic-pass"></a>T.101: ??? How to pass arguments to a variadic template ???
@@ -15612,7 +15623,7 @@ Often a `constexpr` function implies less compile-time overhead than alternative
##### Enforcement ##### Enforcement
* Flag template metaprograms yielding a value. These should be replaced with `constexpr` functions. * Flag template metaprograms yielding a value. These should be replaced with `constexpr` functions.
### <a name="Rt-std-tmp"></a>T.124: Prefer to use standard-library TMP facilities ### <a name="Rt-std-tmp"></a>T.124: Prefer to use standard-library TMP facilities
@@ -15762,7 +15773,7 @@ Use `!=` instead of `<` to compare iterators; `!=` works for more objects becaus
// ... // ...
} }
Of course, range-for is better still where it does what you want. Of course, range-`for` is better still where it does what you want.
##### Example ##### Example
@@ -15891,7 +15902,7 @@ That subset can be compiled with both C and C++ compilers, and when compiled as
int* p1 = malloc(10 * sizeof(int)); // not C++ int* p1 = malloc(10 * sizeof(int)); // not C++
int* p2 = static_cast<int*>(malloc(10 * sizeof(int))); // not C, C-style C++ int* p2 = static_cast<int*>(malloc(10 * sizeof(int))); // not C, C-style C++
int* p3 = new int[10]; // not C int* p3 = new int[10]; // not C
int* p4 = (int*)malloc(10 * sizeof(int)); // both C and C++ int* p4 = (int*) malloc(10 * sizeof(int)); // both C and C++
##### Enforcement ##### Enforcement
@@ -16409,7 +16420,7 @@ This slowdown can be significant compared to `printf`-style output.
##### Example ##### Example
cout << "Hello, World!" << endl; // two output operations and a flush cout << "Hello, World!" << endl; // two output operations and a flush
cout << "hello, World!\n"; // one output operation and no flush cout << "Hello, World!\n"; // one output operation and no flush
##### Note ##### Note
@@ -16546,9 +16557,9 @@ In particular, the single-return rule makes it harder to concentrate error check
// requires Number<T> // requires Number<T>
string sign(T x) string sign(T x)
{ {
if (x<0) if (x < 0)
return "negative"; return "negative";
else if (x>0) else if (x > 0)
return "positive"; return "positive";
return "zero"; return "zero";
} }
@@ -16560,12 +16571,12 @@ to use a single return only we would have to do something like
string sign(T x) // bad string sign(T x) // bad
{ {
string res; string res;
if (x<0) if (x < 0)
res = "negative"; res = "negative";
else if (x>0) else if (x > 0)
res = "positive"; res = "positive";
else else
res ="zero"; res = "zero";
return res; return res;
} }
@@ -16577,7 +16588,7 @@ Of course many simple functions will naturally have just one `return` because of
int index(const char* p) int index(const char* p)
{ {
if (p==nullptr) return -1; // error indicator: alternatively `throw nullptr_error{}` if (p == nullptr) return -1; // error indicator: alternatively "throw nullptr_error{}"
// ... do a lookup to find the index for p // ... do a lookup to find the index for p
return i; return i;
} }
@@ -16587,7 +16598,7 @@ If we applied the rule, we'd get something like
int index2(const char* p) int index2(const char* p)
{ {
int i; int i;
if (p==nullptr) if (p == nullptr)
i = -1; // error indicator i = -1; // error indicator
else { else {
// ... do a lookup to find the index for p // ... do a lookup to find the index for p
@@ -16715,9 +16726,9 @@ This technique is a pre-exception technique for RAII-like resource and error han
void do_something(int n) void do_something(int n)
{ {
if (n<100) goto exit; if (n < 100) goto exit;
// ... // ...
int* p = (int*)malloc(n); int* p = (int*) malloc(n);
// ... // ...
if (some_ error) goto_exit; if (some_ error) goto_exit;
// ... // ...