style: fix code indentation

This commit is contained in:
Thibault Kruse 2016-08-23 11:58:20 +02:00
parent 67191255fa
commit 5aea4a1fef

View File

@ -523,8 +523,8 @@ Some language constructs express intent better than others.
If two `int`s are meant to be the coordinates of a 2D point, say so: If two `int`s are meant to be the coordinates of a 2D point, say so:
draw_line(int, int, int, int); // obscure draw_line(int, int, int, int); // obscure
draw_line(Point, Point); // clearer draw_line(Point, Point); // clearer
##### Enforcement ##### Enforcement
@ -3287,16 +3287,16 @@ This was primarily to avoid code of the form `(a = b) = c` -- such code is not c
##### Example ##### Example
class Foo class Foo
{ {
public: public:
... ...
Foo& operator=(const Foo& rhs) { Foo& operator=(const Foo& rhs) {
// Copy members. // Copy members.
... ...
return *this; return *this;
} }
}; };
##### Enforcement ##### Enforcement
@ -4653,16 +4653,16 @@ A class with members that all have default constructors implicitly gets a defaul
Beware that built-in types are not properly default constructed: Beware that built-in types are not properly default constructed:
struct X { struct X {
string s; string s;
int i; int i;
}; };
void f() void f()
{ {
X x; // x.s is initialized to the empty string; x.i is uninitialized X x; // x.s is initialized to the empty string; x.i is uninitialized
cout << x.s << ' ' << x.i << '\n'; cout << x.s << ' ' << x.i << '\n';
++x.i; ++x.i;
} }
Statically allocated objects of built-in types are by default initialized to `0`, but local built-in variables are not. Statically allocated objects of built-in types are by default initialized to `0`, but local built-in variables are not.
@ -4671,8 +4671,8 @@ Thus, code like the example above may appear to work, but it relies on undefined
Assuming that you want initialization, an explicit default initialization can help: Assuming that you want initialization, an explicit default initialization can help:
struct X { struct X {
string s; string s;
int i {}; // default initialize (to 0) int i {}; // default initialize (to 0)
}; };
##### Enforcement ##### Enforcement
@ -5960,7 +5960,7 @@ Interfaces should normally be composed entirely of public pure virtual functions
unique_ptr<Goof> p {new Derived{"here we go"}}; unique_ptr<Goof> p {new Derived{"here we go"}};
f(p.get()); // use Derived through the Goof interface f(p.get()); // use Derived through the Goof interface
g(p.get()); // use Derived through the Goof interface g(p.get()); // use Derived through the Goof interface
} // leak } // leak
The `Derived` is `delete`d through its `Goof` interface, so its `string` is leaked. The `Derived` is `delete`d through its `Goof` interface, so its `string` is leaked.
Give `Goof` a virtual destructor and all is well. Give `Goof` a virtual destructor and all is well.
@ -6176,8 +6176,8 @@ the more benefits we gain - and the less stable the hierarchy is.
This Shape hierarchy can be rewritten using interface inheritance: This Shape hierarchy can be rewritten using interface inheritance:
class Shape { // pure interface class Shape { // pure interface
public: public:
virtual Point center() const = 0; virtual Point center() const = 0;
virtual Color color() const = 0; virtual Color color() const = 0;
@ -6187,7 +6187,7 @@ This Shape hierarchy can be rewritten using interface inheritance:
virtual void redraw() = 0; virtual void redraw() = 0;
// ... // ...
}; };
Note that a pure interface rarely have constructors: there is nothing to construct. Note that a pure interface rarely have constructors: there is nothing to construct.
@ -6256,8 +6256,8 @@ Now `Shape` is a poor example of a class with an implementation,
but bear with us because this is just a simple example of a technique aimed at more complex hierarchies. but bear with us because this is just a simple example of a technique aimed at more complex hierarchies.
class Impl::Circle : public Circle, public Impl::Shape { // implementation class Impl::Circle : public Circle, public Impl::Shape { // implementation
public: public:
// constructors, destructor // constructors, destructor
int radius() { /* ... */ } int radius() { /* ... */ }
@ -8801,7 +8801,7 @@ comment.
##### Example, bad ##### Example, bad
char *p, c, a[7], *pp[7], **aa[10]; // yuck! char *p, c, a[7], *pp[7], **aa[10]; // yuck!
**Exception**: a function declaration can contain several function argument declarations. **Exception**: a function declaration can contain several function argument declarations.
@ -9124,8 +9124,8 @@ The rules for `{}` initialization are simpler, more general, less ambiguous, and
##### Example ##### Example
int x {f(99)}; int x {f(99)};
vector<int> v = {1, 2, 3, 4, 5, 6}; vector<int> v = {1, 2, 3, 4, 5, 6};
##### Exception ##### Exception
@ -9590,15 +9590,15 @@ Readability: the complete logic of the loop is visible "up front". The scope of
##### Example ##### Example
for (int i = 0; i < vec.size(); i++) { for (int i = 0; i < vec.size(); i++) {
// do work // do work
} }
##### Example, bad ##### Example, bad
int i = 0; int i = 0;
while (i < vec.size()) { while (i < vec.size()) {
// do work // do work
i++; i++;
} }
##### Enforcement ##### Enforcement
@ -10799,7 +10799,7 @@ the same memory. Concurrent programming is tricky for many reasons, most
importantly that it is undefined behavior to read data in one thread after it importantly that it is undefined behavior to read data in one thread after it
was written by another thread, if there is no proper synchronization between was written by another thread, if there is no proper synchronization between
those threads. Making existing single-threaded code execute concurrently can be those threads. Making existing single-threaded code execute concurrently can be
as trivial as adding `std::async` or `std::thread` strategically, or it can as trivial as adding `std::async` or `std::thread` strategically, or it can
necessitate a full rewrite, depending on whether the original code was written necessitate a full rewrite, depending on whether the original code was written
in a thread-friendly way. in a thread-friendly way.
@ -11276,7 +11276,7 @@ If a `thread` joins, we can safely pass pointers to objects in the scope of the
auto q = make_unique<int>(99); auto q = make_unique<int>(99);
raii_thread t3(f, q.get()); // OK raii_thread t3(f, q.get()); // OK
// ... // ...
} }
An `raii_thread` is a `std::thread` with a destructor that joined and cannot be `detached()`. An `raii_thread` is a `std::thread` with a destructor that joined and cannot be `detached()`.
By "OK" we mean that the object will be in scope ("live") for as long as a `thread` can use the pointer to it. By "OK" we mean that the object will be in scope ("live") for as long as a `thread` can use the pointer to it.
@ -11321,7 +11321,7 @@ If a `thread` is detached, we can safely pass pointers to static and free store
t2.detach(); t2.detach();
t3.detach(); t3.detach();
// ... // ...
} }
By "OK" we mean that the object will be in scope ("live") for as long as a `thread` can use the pointers to it. By "OK" we mean that the object will be in scope ("live") for as long as a `thread` can use the pointers to it.
By "bad" we mean that a `thread` may use a pointer after the pointed-to object is destroyed. By "bad" we mean that a `thread` may use a pointer after the pointed-to object is destroyed.
@ -11567,7 +11567,7 @@ Thread creation is expensive.
void master(istream& is) void master(istream& is)
{ {
for (Message m; is >> m; ) for (Message m; is >> m; )
run_list.push_back(new thread(worker, m)); run_list.push_back(new thread(worker, m));
} }
@ -11579,14 +11579,14 @@ Instead, we could have a set of pre-created worker threads processing the messag
void master(istream& is) void master(istream& is)
{ {
for (Message m; is >> m; ) for (Message m; is >> m; )
work.put(n); work.put(n);
} }
void worker() void worker()
{ {
for (Message m; m = work.get(); ) { for (Message m; m = work.get(); ) {
// process // process
} }
} }
@ -12752,20 +12752,20 @@ In such cases, "crashing" is simply leaving error handling to the next level of
void f(int n) void f(int n)
{ {
// ... // ...
p = static_cast<X*>(malloc(n, X)); p = static_cast<X*>(malloc(n, X));
if (p == nullptr) abort(); // abort if memory is exhausted if (p == nullptr) abort(); // abort if memory is exhausted
// ... // ...
} }
Most programs cannot handle memory exhaustion gracefully anyway. This is roughly equivalent to Most programs cannot handle memory exhaustion gracefully anyway. This is roughly equivalent to
void f(int n) void f(int n)
{ {
// ... // ...
p = new X[n]; // throw if memory is exhausted (by default, terminate) p = new X[n]; // throw if memory is exhausted (by default, terminate)
// ... // ...
} }
Typically, it is a good idea to log the reason for the "crash" before exiting. Typically, it is a good idea to log the reason for the "crash" before exiting.
@ -14230,7 +14230,7 @@ Semiregular requires default constructible.
vector<int> v(10); vector<int> v(10);
bool b = 1 == bad; bool b = 1 == bad;
bool b2 = v.size() == bad; bool b2 = v.size() == bad;
} }
} }
This prints `T0` and `Bad`. This prints `T0` and `Bad`.
@ -14587,27 +14587,27 @@ When `concept`s become widely available such alternatives can be distinguished d
There are three major ways to let calling code customize a template. There are three major ways to let calling code customize a template.
template<class T> template<class T>
// Call a member function // Call a member function
void test1(T t) void test1(T t)
{ {
t.f(); // require T to provide f() t.f(); // require T to provide f()
} }
template<class T> template<class T>
void test2(T t) void test2(T t)
// Call a nonmember function without qualification // Call a nonmember function without qualification
{ {
f(t); // require f(/*T*/) be available in caller's scope or in T's namespace f(t); // require f(/*T*/) be available in caller's scope or in T's namespace
} }
template<class T> template<class T>
void test3(T t) void test3(T t)
// Invoke a "trait" // Invoke a "trait"
{ {
test_traits<T>::f(t); // require customizing test_traits<> test_traits<T>::f(t); // require customizing test_traits<>
// to get non-default functions/types // to get non-default functions/types
} }
A trait is usually a type alias to compute a type, A trait is usually a type alias to compute a type,
a `constexpr` function to compute a value, a `constexpr` function to compute a value,
@ -16291,10 +16291,10 @@ Candidates include:
To suppress enforcement of a profile check, place a `suppress` annotation on a language contract. For example: To suppress enforcement of a profile check, place a `suppress` annotation on a language contract. For example:
[[suppress(bounds)]] char* raw_find(char* p, int n, char x) // find x in p[0]..p[n-1] [[suppress(bounds)]] char* raw_find(char* p, int n, char x) // find x in p[0]..p[n-1]
{ {
// ... // ...
} }
Now `raw_find()` can scramble memory to its heart's content. Now `raw_find()` can scramble memory to its heart's content.
Obviously, suppression should be very rare. Obviously, suppression should be very rare.