Merge pull request #210 from tkruse/fix-mdstyle10

Fix style and code examples
This commit is contained in:
Gabriel Dos Reis 2015-09-29 08:40:23 -07:00
commit 6553f69976

View File

@ -324,7 +324,7 @@ Supporting sections:
These sections are not orthogonal.
Each section (e.g., "P" for "Philosophy") and each subsection (e.g., "C.hier" for "Class Hierachies (OOP)") have an abbreviation for ease of searching and reference.
Each section (e.g., "P" for "Philosophy") and each subsection (e.g., "C.hier" for "Class Hierarchies (OOP)") have an abbreviation for ease of searching and reference.
The main section abbreviations are also used in rule numbers (e.g., "C.11" for "Make concrete types regular").
@ -2586,7 +2586,7 @@ Subsections:
**Example**:
void draw(int x, int y, int x2, int y2); // BAD: unnecessary implicit relationships
void draw(Point from, Point to) // better
void draw(Point from, Point to); // better
**Note**: A simple class without virtual functions implies no space or time overhead.
@ -3024,7 +3024,7 @@ The whole purpose of `final_action` is to get a piece of code (usually a lambda)
string s;
int i;
vector<int> vi;
}
};
The default destructor does it better, more efficiently, and can't get it wrong.
@ -3353,7 +3353,7 @@ It is often a good idea to express the invariant as an `Ensure` on the construct
struct Rec2{
string s;
int i;
Rec2(const string& ss, int ii = 0} :s{ss}, i{ii} {} // redundant
Rec2(const string& ss, int ii = 0) :s{ss}, i{ii} {} // redundant
};
Rec r1 {"Foo", 7};
@ -3413,7 +3413,7 @@ The idiom of having constructors acquire resources and destructors release them
// ...
public:
X2(const string& name)
:f{fopen(name.c_str(), "r"}
:f{fopen(name.c_str(), "r")}
{
if (f==nullptr) throw runtime_error{"could not open" + name};
// ...
@ -3438,7 +3438,7 @@ The idiom of having constructors acquire resources and destructors release them
// ...
public:
X3(const string& name)
:f{fopen(name.c_str(), "r"}, valid{false}
:f{fopen(name.c_str(), "r")}, valid{false}
{
if (f) valid=true;
// ...
@ -3451,7 +3451,7 @@ The idiom of having constructors acquire resources and destructors release them
void f()
{
X3 file {Heraclides"};
X3 file {"Heraclides"};
file.read(); // crash or bad read!
// ...
if (is_valid()()) {
@ -3881,6 +3881,7 @@ Types can be defined to move for logical as well as performance reasons.
T* elem;
int sz;
};
}
Vector& Vector::operator=(const Vector& a)
{
@ -4049,6 +4050,7 @@ Consider:
**Example**:
template<typename T>
class X { // OK: value semantics
public:
X();
@ -4134,6 +4136,7 @@ A non-throwing move will be used more efficiently by standard-library and langua
**Example**:
template<typename T>
class Vector {
// ...
Vector(Vector&& a) noexcept :elem{a.elem}, sz{a.sz} { a.sz=0; a.elem=nullptr; }
@ -4148,6 +4151,7 @@ These copy operations do not throw.
**Example, bad**:
template<typename T>
class Vector2 {
// ...
Vector2(Vector2&& a) { *this = a; } // just use the copy
@ -6414,8 +6418,8 @@ or better using concepts
or
double scalbn( // better: x*pow(FLT_RADIX, n); FLT_RADIX is usually 2
double x; // base value
int n; // exponent
double x, // base value
int n // exponent
);
or
@ -6439,7 +6443,7 @@ or
auto s = v.size();
auto h = t.future();
auto q = new int[s];
auto f = [](int x){ return x+10; }
auto f = [](int x){ return x+10; };
In each case, we save writing a longish, hard-to-remember type that the compiler already knows but a programmer could get wrong.
@ -8066,7 +8070,7 @@ One strategy is to add a `valid()` operation to every resource handle:
void f()
{
Vector<string> vs(100); // not std::vector: valid() added
vector<string> vs(100); // not std::vector: valid() added
if (!vs.valid()) {
// handle error or exit
}
@ -8606,7 +8610,7 @@ It also avoids brittle or inefficient workarounds. Convention: That's the way th
int sz;
};
Vector<double> v(10);
vector<double> v(10);
v[7] = 9.9;
**Example, bad**:
@ -9441,14 +9445,14 @@ The two language mechanisms can be use effectively in combination, but a few des
// ...
};
Vector<int> vi;
Vector<string> vs;
vector<int> vi;
vector<string> vs;
It is probably a dumb idea to define a `sort` as a member function of a container,
but it is not unheard of and it makes a good example of what not to do.
Given this, the compiler cannot know if `Vector<int>::sort()` is called, so it must generate code for it.
Similar for `Vector<string>::sort()`.
Given this, the compiler cannot know if `vector<int>::sort()` is called, so it must generate code for it.
Similar for `vector<string>::sort()`.
Unless those two functions are called that's code bloat.
Imagine what this would do to a class hierarchy with dozens of member functions and dozens of derived classes with many instantiations.
@ -10708,7 +10712,7 @@ Pointers should only refer to single objects, and pointer arithmetic is fragile
a[4] = 1; // OK
a[count 1] = 2; // OK
a[count - 1] = 2; // OK
use(a.data(), 3); // OK
}
@ -11966,7 +11970,7 @@ Now `Named` has a default constructor, a destructor, and efficient copy and move
template<typename T> class Vector {
public:
Vector<std::initializer_list<T>);
vector<std::initializer_list<T>>;
// ...
};