Fix whitespace inconsistencies, remove tabs

This commit is contained in:
Thibault Kruse 2016-08-28 11:33:25 +09:00
parent 27b585ad71
commit 603a1b4286

View File

@ -7360,7 +7360,7 @@ What we have here is an "invisible" type error that happens to give a result tha
And, talking about "invisible", this code produced no output: And, talking about "invisible", this code produced no output:
v.x = 123; v.x = 123;
cout << v.d << '\n'; // BAD: undefined behavior cout << v.d << '\n'; // BAD: undefined behavior
###### Alternative ###### Alternative
@ -7394,85 +7394,85 @@ The code is somewhat elaborate.
Handling a type with user-defined assignment and destructor is tricky. Handling a type with user-defined assignment and destructor is tricky.
Saving programmers from having to write such code is one reason for including `variant` in the standard. Saving programmers from having to write such code is one reason for including `variant` in the standard.
class Value { // two alternative representations represented as a union class Value { // two alternative representations represented as a union
private: private:
enum class Tag { number, text }; enum class Tag { number, text };
Tag type; // discriminant Tag type; // discriminant
union { // representation (note: anonymous union) union { // representation (note: anonymous union)
int i; int i;
string s; // string has default constructor, copy operations, and destructor string s; // string has default constructor, copy operations, and destructor
}; };
public: public:
struct Bad_entry { }; // used for exceptions struct Bad_entry { }; // used for exceptions
~Value(); ~Value();
Value& operator=(const Value&); // necessary because of the string variant Value& operator=(const Value&); // necessary because of the string variant
Value(const Value&); Value(const Value&);
// ... // ...
int number() const; int number() const;
string text() const; string text() const;
void set_number(int n); void set_number(int n);
void set_text(const string&); void set_text(const string&);
// ... // ...
}; };
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;
} }
i = n; i = n;
} }
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
type = Tag::text; type = Tag::text;
} }
} }
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:
i = e.i; i = e.i;
break; break;
case Tag::text: case Tag::text:
new(&s)(e.s); // placement new: explicit construct new(&s)(e.s); // placement new: explicit construct
type = e.type; type = e.type;
} }
return *this; return *this;
} }
Value::~Value() Value::~Value()
{ {
if (type==Tag::text) s.~string(); // explicit destroy if (type==Tag::text) s.~string(); // explicit destroy
} }
##### Enforcement ##### Enforcement
@ -7504,12 +7504,12 @@ The idea of `Pun` is to be able to look at the character representation of an `i
If you wanted to see the bytes of an `int`, use a (named) cast: If you wanted to see the bytes of an `int`, use a (named) cast:
void if_you_must_pun(int& x) void if_you_must_pun(int& x)
{ {
auto p = reinterpret_cast<unsigned char*>(&x); auto p = reinterpret_cast<unsigned char*>(&x);
cout << p[0] << '\n'; // undefined behavior cout << p[0] << '\n'; // undefined behavior
// ... // ...
} }
Accessing the result of an `reinterpret_cast` to a different type from the objects declared type is still undefined behavior, Accessing the result of an `reinterpret_cast` to a different type from the objects declared type is still undefined behavior,
but at least we can see that something tricky is going on. but at least we can see that something tricky is going on.
@ -10507,7 +10507,7 @@ Such examples are often handled as well or better using `mutable` or an indirect
Consider keeping previously computed results around for a costly operation: Consider keeping previously computed results around for a costly operation:
int compute(int x); // compute a value for x; assume this to be costly int compute(int x); // compute a value for x; assume this to be costly
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:
@ -10523,7 +10523,7 @@ Consider keeping previously computed results around for a costly operation:
int get_val(int x) int get_val(int x)
{ {
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;
@ -10559,10 +10559,10 @@ State that `cache` is mutable even for a `const` object:
int get_val(int x) const int get_val(int x) const
{ {
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;
} }
// ... // ...
private: private:
@ -10576,10 +10576,10 @@ An alternative solution would to store a pointer to the `cache`:
int get_val(int x) const int get_val(int x) const
{ {
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;
} }
// ... // ...
private: private:
@ -10856,7 +10856,7 @@ Avoid wrong results.
unsigned int y = 7; unsigned int y = 7;
cout << x - y << '\n'; // unsigned result, possibly 4294967286 cout << x - y << '\n'; // unsigned result, possibly 4294967286
cout << x + y << '\n'; // unsigned result: 4 cout << x + y << '\n'; // unsiged result: 4
cout << x * y << '\n'; // unsigned result, possibly 4294967275 cout << x * y << '\n'; // unsigned result, possibly 4294967275
It is harder to spot the problem in more realistic examples. It is harder to spot the problem in more realistic examples.
@ -10906,22 +10906,22 @@ Unsigned arithmetic can yield surprising results if you are not expecting it.
This is even more true for mixed signed and unsigned arithmetic. This is even more true for mixed signed and unsigned arithmetic.
template<typename T, typename T2> template<typename T, typename T2>
T subtract(T x, T2 y) T subtract(T x, T2 y)
{ {
return x-y; return x-y;
} }
void test() void test()
{ {
int s = 5; int s = 5;
unsigned int us = 5; unsigned int us = 5;
cout << subtract(s, 7) << '\n'; // -2 cout << subtract(s, 7) << '\n'; // -2
cout << subtract(us, 7u) << '\n'; // 4294967294 cout << subtract(us, 7u) << '\n'; // 4294967294
cout << subtract(s, 7u) << '\n'; // -2 cout << subtract(s, 7u) << '\n'; // -2
cout << subtract(us, 7) << '\n'; // 4294967294 cout << subtract(us, 7) << '\n'; // 4294967294
cout << subtract(s, us+2) << '\n'; // -2 cout << subtract(s, us+2) << '\n'; // -2
cout << subtract(us, s+2) << '\n'; // 4294967294 cout << subtract(us, s+2) << '\n'; // 4294967294
} }
Here we have been very explicit about what's happening, Here we have been very explicit about what's happening,
but if you had see `us-(s+2)` or `s+=2; ... us-s` would you reliably have suspected that the result would print as `4294967294`? but if you had see `us-(s+2)` or `s+=2; ... us-s` would you reliably have suspected that the result would print as `4294967294`?