-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path03_singleton.html
702 lines (569 loc) · 32.1 KB
/
03_singleton.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<title>3. Singleton: a pattern for regular types</title>
<link rel="stylesheet" href="template/style.css">
</head>
<body>
<span style="float: right">
[
<a href="02_regular_types.html">previous</a>,
<a href="index.html">contents</a>,
<a href="04_instrumented.html">next</a>
]
</span>
<a name="L3.-Singleton:-a-pattern-for-regular-types"></a>
<h1>3. Singleton: a pattern for regular types</h1>
<a name="Learning-C-2b--2b--isn-27-t-as-hard-as-it-appears"></a>
<h2>Learning C++ isn’t as hard as it appears</h2>
<p>I talked to someone and he said “I have been programming in C++ for about eight years, but I never learned C++”.
That is a very common thing.
He was just honestly admitting something which happens to be the case for most people.
Most of us never learn programming languages.
I never learned C++ I was just very
fortunate that I worked next door to the guy who designed C++ so I could
ask questions about why it was doing things.
We learn by osmosis.
We ask each other questions.
I will assume for a second that my friend was right and I will generalize from him to the rest of the class.
Let us figure out together some basic things about C++.</p>
<p>Of course C++ looks very scary if you look at the language description.
It’s about 2,000 pages long and written in incomprehensible legalese.
You stand no chance to ever understand this, it’s just way too long.
I claim that you could write wonderful C++ if you learn about five pages of basic code, not 2,000,
but five and anybody can.</p>
<p>My goal is to make everybody a C++ expert, not to prove that experts are experts.</p>
<a name="Singleton:-a-pattern-for-regular-types"></a>
<h2>Singleton: a pattern for regular types</h2>
<p>Today I wanted to start with one such page which would show us how to write any class.
This class is called <code>singleton</code> and possesses two properties:</p>
<ol>
<li>It is the most simple class possible, meaning it will have no code whatsoever.</li>
<li>It is the most complete class possible, meaning it will have all the language details about class writing which you need to know.</li>
</ol>
<p>After this class is written, you will trim it and put it on your wall,
because any other class will have all these things and more.
When you make any other class, you can start by taking this class and replace
the name <code>singleton</code> and then you just need to fix two or three things.</p>
<a name="Not-the-object-oriented-pattern"></a>
<h3>Not the object oriented pattern</h3>
<p>Some of you might be confused by the name singleton.
All the people
read the “Gang of Four” book<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> and are familiar with singleton pattern<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> and
might think that’s what I’m talking about.
No, I wouldn’t do that, would I?
What I’m talking about is not a pattern, but a very simple class.
It’s similar to a class called <a href="https://en.cppreference.com/w/cpp/utility/pair"><code>std::pair</code></a>.
If you go and check a dictionary it says: singleton, pair, triple, quadruple, etc.
A pair has two things, well singleton has just one thing.</p>
<a name="Template-and-type-functions"></a>
<h3>Template and type functions</h3>
<p>Let’s start with:</p>
<pre><code>template <typename T>
</code></pre>
<p>Some people get scared when they hear <code>template</code>.
Why do I need template? Because we want to write something which takes one type and returns
another type.
Let’s forget C++ for a second.
Mathematically speaking we want to write a type function: a thing which takes a type in
and generates new types.
The <code>template</code> is the mechanism in C++ for doing just that.</p>
<p>There are of course other type functions, even type functions in C.
For example, we want to take a type we want to take an <code>int</code> and convert it to some other type.
Can you think of one?
What about <a href="https://en.cppreference.com/w/cpp/language/sizeof"><code>sizeof</code></a>?
No, this does not return a type.
But it is a wonderful example of a <strong>type attribute</strong>,
something which maps type into value.
What about macro?
Macro for sure has now no effects on type system<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup>.
What about pointer?
Yes. The pointer star is a type function.</p>
<pre><code>int*
</code></pre>
<p>It takes type int, double, etc and returns another type.
You write it postfix but it is logically a type function.</p>
<a name="Guidelines-for-writing-classes"></a>
<h3>Guidelines for writing classes</h3>
<p>Now let’s start our class, with a field for value:</p>
<pre><code>template <typename T>
struct singleton
{
T value;
};
</code></pre>
<p>What is the difference between a class and a struct?
The only difference is how they treat public and private.
They’re fundamentally the same.
If I say <code>struct</code> the default field accessibility is public. If I say <code>class</code> the default is private.</p>
<p>Some would say, “let us make value private because
that’s object-oriented way”.
“We will provide people with two functions: set value, and get value.”
That is good because it makes your productivity go up.
You could report that you wrote two more lines of code (joke).
On the other hand, it is idiotic because the only reason you want that is to read and write in a peculiar way,
not the way the language intends, which is just using the assignment operator.
It doesn’t protect anything<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup>.</p>
<p>That does bring us to another question.
What do we need to make private?
When you should not be able to set a value.
A canonical example is something like <code>std::vector</code>.
Internally, it has a pointer to a memory area where all the data is allocated.
You don’t want to have this thing public because if somebody writes into there,
you’re going to be leaking memory.
There is no reason to write to it before you first deallocate.
Another way to think about it is to help preserve an invariant.
There is some condition we need to assure that the values cannot change.</p>
<p>For <code>singleton</code>, we pick <code>struct</code> because it’s less typing.
<em>We should find the most minimal way of saying what we want to say</em>.</p>
<a name="Semi-2d-regular-singleton"></a>
<h2>Semi-regular singleton</h2>
<p>When we implement this class, we want people to feel as good about it as they feel about <code>int</code>.
It has to be natural, so all the functions they would normally write for <code>int</code> would just work for this class.
Not of course plus, minus, divide, etc but the basic fundamental stuff should work the same.
Even people who don’t understand logic behind STL still
manage to use <code>std::vector</code> because
vector behaves in somewhat natural way.</p>
<p>For example, we want to be able to support conditional initialization:</p>
<pre><code>T a;
if (something) a = b;
else a = c;
</code></pre>
<p>To support this we need:</p>
<pre><code>T a;
a = b;
</code></pre>
<p>to be identical (hopefully even in performance), to:</p>
<pre><code>T a(b);
</code></pre>
<p>Now, let’s provide the operations to make it semi-regular.
We will start with constructors:</p>
<pre><code>// semiregular
singleton(const singleton& x) : value(x.value) {}
// could be implicitly declared
singleton() {}
~singleton() {}
singleton& operator=(const singleton& x) {
value = x.value;
return *this;
}
</code></pre>
<p>What are the semantics of the default constructor?
In this case you want whatever the default value of <code>T</code> is, to be constructed.
The compiler will do this for us.</p>
<p>What will the default value of <code>T</code> be when it’s a pointer type?
Just some random address, which is fine.
The two properties of default constructed value of <code>T</code> on which you
can rely are:</p>
<ol>
<li>You can assign to it.</li>
<li>You can destroy it.</li>
</ol>
<p>A pointer to a random address satisfies these requirements.</p>
<p>The default constructor will always be synthesized by the compiler unless you have another constructor.
It turns out, you usually want multiple constructors.
Therefore it’s very unsafe to depend on.
You put additional constructor, and bam whole bunch of stuff stops compiling, very unpleasant.</p>
<a name="Optimize-the-common-case"></a>
<h3>Optimize the common case</h3>
<p>In the assignment operator do we need to do anything special when assigning a value to itself (<code>x = x</code>)?
It’s a thing <a href="https://en.wikipedia.org/wiki/Scott_Meyers">Scott Meyers</a> says you should check for with <code>if (x == x)</code><sup id="fnref:5"><a href="#fn:5" rel="footnote">5</a></sup>,
but you don’t need to check, just consider what will happen if they are equal.
It will just assign back to itself.
It might do extra work.
But, you don’t want to optimize the case which is once in a blue moon while slowing every other case.
Believe it or not when we do timing experiments we will learn conditionals are very very expensive and getting to be more and more expensive.
Assignments are getting to be free.
The processor could schedule them in parallel.
There is just enough hardware to do that so don’t break the pipeline.</p>
<p>Compiler writers don’t read Scott Meyers, fortunately for us.
You have to learn to think because he doesn’t.
He just gives you this rule, number 173.
If you follow the rule the code will be good.
No.
You have to think.
Then the code will be good.</p>
<a name="Virtual-functions-2c--virtual-destructors-2c--and-OOP"></a>
<h3>Virtual functions, virtual destructors, and OOP</h3>
<p>Add a destructor:</p>
<pre><code>~singleton() {}
</code></pre>
<p>If you interview for a job and there is a manager who knows
nothing at all about programming or C++, what is the one question he asks you?
“Why should you always make a destructor virtual?”<sup id="fnref:6"><a href="#fn:6" rel="footnote">6</a></sup>
This is frightening thing for me because I lived my life
until now, without ever making a single destructor virtual.
Believe it or not most of my destructors are part of the standard library.</p>
<p>All the great authorities on C++ such as <a href="https://en.wikipedia.org/wiki/Scott_Meyers">Scott Meyers</a> who
people think invented C++ are idealized in books like “Effective C++”,
“Effective STL”, “effective everything”.
He tells you always declare destructor as virtual<sup id="fnref:7"><a href="#fn:7" rel="footnote">7</a></sup>.
OK, he’s wrong. Simple as that.</p>
<p>What do we want to create? Take type <code>T</code>, put it in a struct. Will the size of the thing increase?
No. It has no overhead.
Singleton is the same size as <code>T</code>.
It’s the wonderful thing about singleton, and lets you pack them in arrays.
If you add <code>virtual</code> to the destructor, the size will dramatically grow.
Why would I put virtual? Because some really crazy person would want to
inherit something virtually from this? He needs counseling.
Not a single class in the standard library does it.</p>
<p>You have all heard that C++ is a multi-paradigm language.
What it means is once upon a time it was an object-oriented language.
Then some people chased it away and said you could program differently.
I am showing you how you could program differently.
If you program in an object-oriented way then many good things might happen.
I don’t know what they are but you are not going to be efficient.
Bjarne used to joke that object
oriented systems are those that have slow graphics.</p>
<p>As time progresses, <code>++</code> is getting faster and faster and virtual function is getting slower and slower.
Their spread is growing and we’re not going to address
any parts of C++ in this course which slow the computations.</p>
<p>If you want to learn about virtual I’m sure there are lots
of people here who would clearly advocate object-oriented programming,
but I’m not one of them.
I destroyed my career by becoming this sworn enemy of object-oriented a long time ago.
I am yet to see a situation where it’s helpful.
I’m not denying that it’s theoretically possible to find a good piece of code written with virtual functions. I am just stating the fact I haven’t seen one yet.</p>
<a name="Regular-singleton"></a>
<h2>Regular singleton</h2>
<p>For regular types we must define equality.</p>
<pre><code>// regular
friend
bool operator==(const singleton& x, const singleton& y) {
return x.value == y.value;
}
friend
bool operator!=(const singleton& x, const singleton& y) {
return !(x == y);
}
</code></pre>
<p>Recall that we decided not to define these as member functions, because they are symmetric.
<code>friend</code> functions inside the class declaration are not member functions,
but still have all the access to all the members (not that we care here).
More importantly this signature is nice.
If you put it outside you discover you have to write an ugly thing.</p>
<a name="Equality-and-the-three-laws-of-thought"></a>
<h3>Equality and the three laws of thought</h3>
<p>We have to define what equality is
and it has to satisfy some very basic rules.
There is one great law on which the entire edifice of civilization
is based. It is called the <strong>law of identity</strong>
and goes with two other fundamental laws of thought <sup id="fnref:8"><a href="#fn:8" rel="footnote">8</a></sup>:</p>
<p><strong>The law of identity</strong>: a == a. Popeye the Sailor used to say, “I am, what I am”.</p>
<p>Computers do not obey such law.
There is a fundamental case which breaks and has consequences.</p>
<p><strong>Exercise:</strong> If you don’t believe me, try to figure out a type which violates the law of identity (solved in chapter 6).</p>
<p><strong>The law of non-contradiction</strong>: You cannot have a predicate <code>P</code> be true and <code>!P</code> be true at the same time.</p>
<p><strong>The law of excluded middle</strong>: Every predicate <code>P</code> must be either true, or false.</p>
<p>Everybody from Plato all the way up to <a href="https://en.wikipedia.org/wiki/Ayn_Rand">Ayn Rand</a>, the greatest American mind (joke).
Whatever her political views, even she, <a href="https://plato.stanford.edu/entries/ayn-rand/supplement.html#ExisIdenCons">supported</a> the law of identity.
There is a lot to figure out.
There is deep stuff about equality<sup id="fnref:9"><a href="#fn:9" rel="footnote">9</a></sup>.</p>
<a name="Why-can-27-t-the-compiler-generate--3d--3d--and--21--3d--3f-"></a>
<h3>Why can’t the compiler generate == and !=?</h3>
<p>Equality should be implicitly declared by the compiler, but it isn’t.
It’s not in C++11 or C++14.
This goes back to problems C++ inherited from C.
C is a very great language in some respects but
it also was a homegrown thing without some particularly deep thinking.
Initially they didn’t have structs.
Then they had structs, but they couldn’t pass them.
They were not copyable and you couldn’t pass them as arguments.
Then they fixed it.
They said, “we’ll just copy the bits” and things would work.</p>
<p>Equality is defined for all built-in types: <code>int</code>, <code>double</code>, <code>short</code>, <code>char</code>, pointers, etc.
So, if you have a struct, why can’t you generate an equality that uses those?
Two things are equal if all their members are equal.
It’s a sensible rule a compiler could do.</p>
<p>I never managed to ask Dennis Ritchie about it.
But, I asked probably the second best person on the subject, <a href="https://en.wikipedia.org/wiki/Stephen_C._Johnson">Steve Johnson</a>, because
he actually implemented all these assignments for structures and things like that.
Steve told me, “it was very hard because the bits in the padding might not be equal.
If you compare bit by bit things which have equal members, but not equal bits in the padding, it will not work”<sup id="fnref:10"><a href="#fn:10" rel="footnote">10</a></sup>.</p>
<p>But, why should you compare bit by bit?
You should do recursive member by member as we discovered.
But C didn’t do it.</p>
<p>But, here we come to something even more egregious.
I just defined equality.
It’s utterly horrible that I have to now define inequality because
what’s the meaning of inequality?
Not equality. Could there be any other meaning?</p>
<p>In 1994 I proposed such a thing to the standard committee.
I even proposed bunch of templates which will automatically do it.
They threw them out because there were people who said, “but we want to have the freedom to make the
glyph <code>!=</code> do something else.”
I literally have no words because that is not freedom.
It’s like saying I want to have freedom to run on the street with no pants!
The semantics must be fixed, you have no right
to define inequality which will do a semantically different thing.</p>
<p>What if you determine something is unequal faster?
I don’t know such examples but supposing there was, that is fine.
in 99% of the cases it should just be defined (and optionally manually defined).</p>
<p>Notice that we didn’t define <code>!=</code> as:</p>
<pre><code>return x.value != y.value;
</code></pre>
<p>Why? Because by defining one in terms of the other,
it can always stay the way it is, even if we copy it to other classes.</p>
<a name="Totally-ordered-singleton"></a>
<h2>Totally ordered singleton</h2>
<p>To make <code>singleton</code> <code>TotallyOrdered</code> we need to define <code><</code> and
related operators.</p>
<pre><code>// totally ordered
friend
bool operator<(const singleton& x, const singleton& y) {
return x.value < y.value;
}
friend
bool operator>(const singleton& x, const singleton& y) {
return (y < x);
}
friend
bool operator<=(const singleton& x, const singleton& y) {
return !(y < x);
}
friend
bool operator>=(const singleton& x, const singleton& y) {
return !(x < y);
}
</code></pre>
<p>I chose <code><</code> as the primary one out of four.
Considering comparison applied to sorting, you could sort in ascending order or in descending order.
It seems to be natural to pick ascending.
If I asked you to name a bunch of numbers, you would say “one, two, three, four, five”.
Only strange people will say “five, four, three, two, one”.
Natural numbers go from one up.</p>
<p>Even though most of the STL algorithms only use <code><</code> you should still define all the others.
I’m not going to use the others, but I will provide them for other people to use.
There is a rule used in the <a href="https://en.wikipedia.org/wiki/Robustness_principle">internet protocol</a> that you should assume to do everything for your clients,
but expect nothing from them.</p>
<p>Understand how all the other operators are defined in terms of <code><</code>.
Contemplate it.
It’s really important.
It is mathematics, but that’s mathematics every programmer should be able to do.</p>
<a name="Specifying-concepts"></a>
<h3>Specifying concepts</h3>
<p>Now let’s talk about what kind of type <code>T</code> could be.
Because we implemented all these operators,
<code>T</code> could be <code>SemiRegular</code>, <code>Regular</code>, or <code>TotallyOrdered</code>.
These are requirements on the type <code>T</code>, otherwise known
as <strong>concepts</strong>.</p>
<p>The C++ language doesn’t have support for concepts at this time<sup id="fnref:11"><a href="#fn:11" rel="footnote">11</a></sup>.
So, we use comments to communicate them.</p>
<p>In <code>singleton</code> we add a comment to describe this:</p>
<pre><code>// T is semiregular, or regular, or totally-ordered.
</code></pre>
<p>It’s a good example of a <strong>disjunctive concept</strong>.
<code>T</code> could be any of them.</p>
<p>You might wonder how <code>==</code> will work, if you plug-in only a type <code>T</code>
which is only <code>SemiRegular</code>.
In C++, things don’t have to be defined unless they are used.
This is a wonderful property on which we are relying.
If you give me <code>T</code> which has no equality, it is fine.
It will give me singleton of <code>T</code>
which will have copy constructor and assignment but will not have equality.
If <code>T</code> has an equality, then singleton will have equality.
Same for total ordering, etc.</p>
<p><strong>Exercise:</strong> Copy the file for singleton and modify it to write <code>pair</code>.</p>
<a name="Implicit-type-conversion"></a>
<h2>Implicit type conversion</h2>
<p>Since we wrote a few constructors for <code>singleton</code> we should
talk a bit about implicit type conversions.</p>
<p>Once upon a time people invented strong typing.
When they did, they said everything has to have a type.
If you want to make it into a different type you have to convert it, by calling a function.
Makes sense, right?
But, our friends at <a href="https://en.wikipedia.org/wiki/Bell_Labs">Bell Labs</a> thought it was a bad idea.
They said, “I don’t want to write the conversion functions”.
Therefore they invented something called implicit conversions.</p>
<p>In C it converts integers to float.
Why did these Bell Labs guys introduce such a thing?
Were they mad?
It was because they were lazy.
They couldn’t do it elegantly because they didn’t
have <a href="https://en.cppreference.com/w/cpp/language/overload_resolution">function overloading</a>.</p>
<p>In C++ we have <code>sqrt(int)</code>, <code>sqrt(double)</code>, etc
You can pass <code>int</code>, or <code>double</code> and it does the right thing.
Without overloading they had two choices.</p>
<ol>
<li>Introduce <code>sqrt_double</code>, <code>sqrt_float</code>, <code>sqrt_int</code>, etc
(and implement them all separately).</li>
<li>Introduce a palliative (a solution which sort of works).
We will just promote everything to the highest
possible type and obviously it’s <code>double</code>.</li>
</ol>
<p>When C++ came about they couldn’t just reject the legacy of C.
One of the deals was that the C++ compiler had to compile the entire
UNIX codebase and there was only one place where it broke.
In UNIX there is a system call <a href="https://linux.die.net/man/2/stat"><code>stat</code></a> which returns a struct <code>stat</code>.
But, in C++ structs and functions live in the
same namespace the function <code>stat</code> is a constructor for structure <code>stat</code> which it isn’t.
So they had to find workarounds.</p>
<p>But, generally they had this wonderful goal of retaining full compatibility with C.
They said, “we will keep implicit conversions.”
I wish they just did keep them the way they were in C but then
they said, “oh but we have to extend them. This is a wonderful thing which we need
to make work for any other type”.
So, implicit conversions work for all types and the rules are <a href="https://en.cppreference.com/w/cpp/language/implicit_conversion">extremely complicated</a> so this is the only time I’m going to mention them.</p>
<p>Here are the rules:
If you have a conversion from one user defined type to another,
the compiler will look for all the one-step user defined conversions.
Fortunately it is not going to look for
two, three, four, five steps because you know there is combinatorial explosion.</p>
<p>But, it doesn’t stop there.
On top of user-defined conversion you could put one more layer of built-in conversions.
If you have a class which is convertible to <code>int</code> and a function
which takes <code>double</code>.
You could give me the element of a class and it will work.
It seems not to be a big deal,
but then people started writing code like</p>
<pre><code>std::cin << 42
</code></pre>
<p>You would think it couldn’t possibly work.
They’re trying to write into an input stream.
But, it did.</p>
<p><code>std::cin</code> is convertible to a pointer.
If it fails, it returns <code>null</code> with type <code>void*</code>.
Since it is convertible to a pointer, you can apply one
more conversion and convert this pointer to a Boolean.
Then you could convert it to an integer.
So <code>std::cin</code> becomes zero and you shifted by forty-two positions.
Isn’t that beautiful (joke)?</p>
<p>The problem is they fixed this problem by
inventing things called explicit conversion.
But then the <code>while</code> statement stopped working:</p>
<p>So they had to break the rule.
Explicit conversions are not going to be called implicitly, unless
they are in <code>while</code>, <code>if</code>, and other conditions which people used for input streams.
So, the entire type system is screwed up (technical term), to work around some
ancient design feature.
The end of the story is avoid implicit conversions.
Never rely on them, it’s impossible to avoid them.
Even if you declare everything explicit there is still a
context in C++ where implicit conversion will be done.
You should never rely on one type
automatically becoming another.</p>
<p>There are some specialists on C++, even specialists
on STL, who write that STL totally depends on implicit conversions. This
is false. Of course it handles implicit conversions, what else could it do?</p>
<a name="Code"></a>
<h2>Code</h2>
<ul>
<li><a href="code/singleton.h">singleton.h</a></li>
<li><a href="code/test_singleton.cpp">test_singleton.cpp</a></li>
</ul>
<div class="footnotes">
<hr/>
<ol>
<li id="fn:1">
“Gang of four” is a nickname for an influential text in object oriented programming called <a href="https://en.wikipedia.org/wiki/Design_Patterns">“Design Patterns”</a>
by Gamma, Helm, Johnson, and Vlissides.
As the name suggests, the book studies patterns of ways to organize code and objects to solve common problems
while aiming to preserve modularity and flexibility.<a href="#fnref:1" rev="footnote">↩</a></li>
<li id="fn:2">
A <a href="https://www.oodesign.com/singleton-pattern.html">singleton</a> in object oriented programming is a class which is intended to have one instance,
or at least one canonical instance, which all code can reference.<a href="#fnref:2" rev="footnote">↩</a></li>
<li id="fn:3">
Macro systems typically manipulate only the text of the code itself, and thus have no
access to compiler data.
Expanding all the macros to create new source code,
and then compiling the resulting macro-less code
would give equivalent output.<a href="#fnref:3" rev="footnote">↩</a></li>
<li id="fn:4">
<p>Alex: Don’t be so eager with making members of classes private.
I’m a communist, I don’t like private property.
OK, I’m not really a communist.
Someone accused me of being one for not liking object-oriented programming.
They said STL was basically communist propaganda.
Objects are important because they own things.</p>
<p>This same person made a million dollars selling my code.
I’m not making it up.
I worked for <a href="https://en.wikipedia.org/wiki/HP_Labs">HP labs</a>.
But, HP couldn’t use code from research,
because researchers don’t know anything.
So, they bought it from this guy.
The only thing he did is run it through a pretty printer
which made it unreadable.
I didn’t get a kickback.
My income from STL is about $750.
I got $250 for writing an <a href="http://stepanovpapers.com/BYTE_com.htm">article</a> for BYTE magazine.
I got $500 for an invited keynote at <a href="https://en.wikipedia.org/wiki/OOPSLA">oopsla</a>.
I paid taxes from both.</p><a href="#fnref:4" rev="footnote">↩</a></li>
<li id="fn:5">
See item 17 in “Effective C++”.<a href="#fnref:5" rev="footnote">↩</a></li>
<li id="fn:6">
Making a destructor virtual ensures that if a class
inherits virtually and is destructed, then the base class destructor is called too.<a href="#fnref:6" rev="footnote">↩</a></li>
<li id="fn:7">
<p>In “Effective C++”, Scott Meyers does not say to use <code>virtual</code>
on every destructor, he specifies “make sure base classes have virtual destructors”
and clarifies “gratuitously declaring all destructors virtual is just as wrong
as never declaring them virtual”.
He provides a heuristic, “declare a virtual destructor in a class
if and only if that class contains at least one virtual function.”</p>
<p>Alex is wrong about Scott’s recommendation.
But for whatever reason, this incorrect recommendation that
we should always use <code>virtual</code> destructors was repeated
and enforced in code linters at many organizations for a long time.
I have personally had the question come up in several C++ interviews.
It’s likely that defenders of this practice incorrectly invoked
Scott’s name.</p><a href="#fnref:7" rev="footnote">↩</a></li>
<li id="fn:8">
<p>The “laws of thought” referenced here by Alex
are generally attributed to Aristotle.
Here is an expression of the Law of non-contradiction
in the <a href="http://classics.mit.edu/Aristotle/metaphysics.4.iv.html">Metaphysics</a>:</p>
<blockquote><p>We have now posited that it is impossible for anything at the same time to be and not to be, and by this means have shown that this is the most indisputable of all principles.
Some indeed demand that even this shall be demonstrated, but this they do through want of education, for not to know of what things one should demand demonstration, and of what one should not, argues want of education.
For it is impossible that there should be demonstration of absolutely everything (there would be an infinite regress, so that there would still be no demonstration);
but if there are things of which one should not demand demonstration, these persons could not say what principle they maintain to be more self-evident than the present one. (Book 4)</p></blockquote><a href="#fnref:8" rev="footnote">↩</a></li>
<li id="fn:9">
There is a branch of logic
called <a href="https://en.wikipedia.org/wiki/Intuitionistic_logic">intuitionism</a>,
closely associated with <a href="https://en.wikipedia.org/wiki/Constructivism_(philosophy_of_mathematics)">constructivism</a> which
denies the Law of excluded middle.
Specifically, it takes issue with the idea that <code>!(!P)</code>, is the same as <code>P</code>.
Modern <a href="https://plato.stanford.edu/entries/dialetheism/">philosophers</a> have even questioned the law of non-contradiction.
But, I know of no serious mathematical or philosophical
movements denying the law of identity.<a href="#fnref:9" rev="footnote">↩</a></li>
<li id="fn:10">
<p>Padding is a technical fact about how C prepares data to be stored in memory.
The compiler is not only concerned with memory usage,
but also how the CPU will address that memory.
Suppose you write the following:</p>
<pre><code>typedef struct
{
uint16_t id;
uint32_t number;
} Record;
</code></pre>
<p>A typical compiler will insert 16 hidden padding bits between <code>id</code> and <code>number</code>,
so that all the fields in the structure begin at addresses
which are multiples of 32 bits.
Even if you assign all the fields:</p>
<pre><code>Record r;
r.id = 1;
r.number = 20;
</code></pre>
<p>The invisible padding bits will not be modified,
and so their values are undefined.
You can read more <a href="https://en.cppreference.com/w/c/language/object">here</a>.</p><a href="#fnref:10" rev="footnote">↩</a></li>
<li id="fn:11">
<a href="https://en.wikipedia.org/wiki/Concepts_(C%2B%2B)">Concepts</a> as a language feature went through many
iterations and delays before finally being included in the C++20 standard.
When the course was given, a group at A9 (including Alex) was working to get them included in C++14.
You can read their <a href="papers/concepts-proposal.pdf">proposal</a>.
Bjarne actually visits A9 to give a guest lecture on concepts as part of the course,
however this is not included in the notes as it is a departure from the rest of the material.<a href="#fnref:11" rev="footnote">↩</a></li>
</ol>
</div>
<span style="float: right">
[
<a href="02_regular_types.html">previous</a>,
<a href="index.html">contents</a>,
<a href="04_instrumented.html">next</a>
]
</span>
</body>
</html>