annotate flang/docs/C++style.md @ 223:5f17cb93ff66 llvm-original

LLVM13 (2021/7/18)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 18 Jul 2021 22:43:00 +0900
parents 79ff65ed7e25
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 <!--===- docs/C++style.md
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
2
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 See https://llvm.org/LICENSE.txt for license information.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 -->
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
8
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 # Flang C++ Style Guide
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 ```eval_rst
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 .. contents::
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 :local:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 This document captures the style guide rules that are followed in the Flang codebase.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
17
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 ## In brief:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 * Use *clang-format*
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 from llvm 7
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 on all C++ source and header files before
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 every merge to master. All code layout should be determined
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 by means of clang-format.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 * Where a clear precedent exists in the project, follow it.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 * Otherwise, where [LLVM's C++ style guide](https://llvm.org/docs/CodingStandards.html#style-issues)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 is clear on usage, follow it.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 * Otherwise, where a good public C++ style guide is relevant and clear,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 follow it. [Google's](https://google.github.io/styleguide/cppguide.html)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 is pretty good and comes with lots of justifications for its rules.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 * Reasonable exceptions to these guidelines can be made.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 * Be aware of some workarounds for known issues in older C++ compilers that should
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 still be able to compile f18. They are listed at the end of this document.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
33
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 ## In particular:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
35
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 Use serial commas in comments, error messages, and documentation
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 unless they introduce ambiguity.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
38
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 ### Error messages
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 1. Messages should be a single sentence with few exceptions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 1. Fortran keywords should appear in upper case.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 1. Names from the program appear in single quotes.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 1. Messages should start with a capital letter.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 1. Messages should not end with a period.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
45
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 ### Files
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 1. File names should use dashes, not underscores. C++ sources have the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 extension ".cpp", not ".C" or ".cc" or ".cxx". Don't create needless
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 source directory hierarchies.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 1. Header files should be idempotent. Use the usual technique:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 #ifndef FORTRAN_header_H_
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 #define FORTRAN_header_H_
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 // code
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 #endif // FORTRAN_header_H_
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 1. `#include` every header defining an entity that your project header or source
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 file actually uses directly. (Exception: when foo.cpp starts, as it should,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 with `#include "foo.h"`, and foo.h includes bar.h in order to define the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 interface to the module foo, you don't have to redundantly `#include "bar.h"`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 in foo.cpp.)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 1. In the source file "foo.cpp", put its corresponding `#include "foo.h"`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 first in the sequence of inclusions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 Then `#include` other project headers in alphabetic order; then C++ standard
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 headers, also alphabetically; then C and system headers.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 1. Don't use `#include <iostream>`. If you need it for temporary debugging,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 remove the inclusion before committing.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
68
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 ### Naming
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 1. C++ names that correspond to well-known interfaces from the STL, LLVM,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 and Fortran standard
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 can and should look like their models when the reader can safely assume that
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 they mean the same thing -- e.g., `clear()` and `size()` member functions
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 in a class that implements an STL-ish container.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 Fortran intrinsic function names are conventionally in ALL CAPS.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 1. Non-public data members should be named with leading miniscule (lower-case)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 letters, internal camelCase capitalization, and a trailing underscore,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 e.g. `DoubleEntryBookkeepingSystem myLedger_;`. POD structures with
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 only public data members shouldn't use trailing underscores, since they
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 don't have class functions from which data members need to be distinguishable.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 1. Accessor member functions are named with the non-public data member's name,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 less the trailing underscore. Mutator member functions are named `set_...`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 and should return `*this`. Don't define accessors or mutators needlessly.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 1. Other class functions should be named with leading capital letters,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 CamelCase, and no underscores, and, like all functions, should be based
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 on imperative verbs, e.g. `HaltAndCatchFire()`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 1. It is fine to use short names for local variables with limited scopes,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 especially when you can declare them directly in a `for()`/`while()`/`if()`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 condition. Otherwise, prefer complete English words to abbreviations
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 when creating names.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
91
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 ### Commentary
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 1. Use `//` for all comments except for short `/*notes*/` within expressions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 1. When `//` follows code on a line, precede it with two spaces.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 1. Comments should matter. Assume that the reader knows current C++ at least as
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 well as you do and avoid distracting her by calling out usage of new
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 features in comments.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
98
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 ### Layout
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 Always run `clang-format` on your changes before committing code. LLVM
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 has a `git-clang-format` script to facilitate running clang-format only
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 on the lines that have changed.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
103
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 Here's what you can expect to see `clang-format` do:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 1. Indent with two spaces.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 1. Don't indent public:, protected:, and private:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 accessibility labels.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 1. Never use more than 80 characters per source line.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 1. Don't use tabs.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 1. Don't indent the bodies of namespaces, even when nested.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 1. Function result types go on the same line as the function and argument
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 names.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
113
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 Don't try to make columns of variable names or comments
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 align vertically -- they are maintenance problems.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
116
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 Always wrap the bodies of `if()`, `else`, `while()`, `for()`, `do`, &c.
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
118 with braces, even when the body is a single statement or empty. Note that this
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
119 diverges from the LLVM coding style. In parts of the codebase that make heavy
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
120 use of LLVM or MLIR APIs (e.g. the Lower and Optimizer libraries), use the
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
121 LLVM style instead. The
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 opening `{` goes on
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 the end of the line, not on the next line. Functions also put the opening
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 `{` after the formal arguments or new-style result type, not on the next
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 line. Use `{}` for empty inline constructors and destructors in classes.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
126
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 If any branch of an `if`/`else if`/`else` cascade ends with a return statement,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 they all should, with the understanding that the cases are all unexceptional.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 When testing for an error case that should cause an early return, do so with
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 an `if` that doesn't have a following `else`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
131
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 Don't waste space on the screen with needless blank lines or elaborate block
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 commentary (lines of dashes, boxes of asterisks, &c.). Write code so as to be
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 easily read and understood with a minimum of scrolling.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
135
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 Avoid using assignments in controlling expressions of `if()` &c., even with
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 the idiom of wrapping them with extra parentheses.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
138
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 In multi-element initializer lists (especially `common::visitors{...}`),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 including a comma after the last element often causes `clang-format` to do
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 a better jobs of formatting.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
142
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 ### C++ language
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 Use *C++17*, unless some compiler to which we must be portable lacks a feature
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 you are considering.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 However:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 1. Never throw or catch exceptions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 1. Never use run-time type information or `dynamic_cast<>`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 1. Never declare static data that executes a constructor.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 (This is why `#include <iostream>` is contraindicated.)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 1. Use `{braced initializers}` in all circumstances where they work, including
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 default data member initialization. They inhibit implicit truncation.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 Don't use `= expr` initialization just to effect implicit truncation;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 prefer an explicit `static_cast<>`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 With C++17, braced initializers work fine with `auto` too.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 Sometimes, however, there are better alternatives to empty braces;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 e.g., prefer `return std::nullopt;` to `return {};` to make it more clear
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 that the function's result type is a `std::optional<>`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 1. Avoid unsigned types apart from `size_t`, which must be used with care.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 When `int` just obviously works, just use `int`. When you need something
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 bigger than `int`, use `std::int64_t` rather than `long` or `long long`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 1. Use namespaces to avoid conflicts with client code. Use one top-level
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 `Fortran` project namespace. Don't introduce needless nested namespaces within the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 project when names don't conflict or better solutions exist. Never use
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 `using namespace ...;` outside test code; never use `using namespace std;`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 anywhere. Access STL entities with names like `std::unique_ptr<>`,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 without a leading `::`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 1. Prefer `static` functions over functions in anonymous namespaces in source files.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 1. Use `auto` judiciously. When the type of a local variable is known,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 monomorphic, and easy to type, be explicit rather than using `auto`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 Don't use `auto` functions unless the type of the result of an outlined member
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 function definition can be more clear due to its use of types declared in the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 class.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 1. Use move semantics and smart pointers to make dynamic memory ownership
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 clear. Consider reworking any code that uses `malloc()` or a (non-placement)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 `operator new`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 See the section on Pointers below for some suggested options.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 1. When defining argument types, use values when object semantics are
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 not required and the value is small and copyable without allocation
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 (e.g., `int`);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 use `const` or rvalue references for larger values (e.g., `std::string`);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 use `const` references to rather than pointers to immutable objects;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 and use non-`const` references for mutable objects, including "output" arguments
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 when they can't be function results.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 Put such output arguments last (_pace_ the standard C library conventions for `memcpy()` & al.).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 1. Prefer `typename` to `class` in template argument declarations.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 1. Prefer `enum class` to plain `enum` wherever `enum class` will work.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 We have an `ENUM_CLASS` macro that helps capture the names of constants.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 1. Use `constexpr` and `const` generously.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 1. When a `switch()` statement's labels do not cover all possible case values
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 explicitly, it should contain either a `default:;` at its end or a
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 `default:` label that obviously crashes; we have a `CRASH_NO_CASE` macro
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 for such situations.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 1. On the other hand, when a `switch()` statement really does cover all of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 the values of an `enum class`, please insert a call to the `SWITCH_COVERS_ALL_CASES`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 macro at the top of the block. This macro does the right thing for G++ and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 clang to ensure that no warning is emitted when the cases are indeed all covered.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 1. When using `std::optional` values, avoid unprotected access to their content.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 This is usually by means of `x.has_value()` guarding execution of `*x`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 This is implicit when they are function results assigned to local variables
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 in `if`/`while` predicates.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 When no presence test is obviously protecting a `*x` reference to the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 contents, and it is assumed that the contents are present, validate that
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 assumption by using `x.value()` instead.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 1. We use `c_str()` rather than `data()` when converting a `std::string`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 to a `const char *` when the result is expected to be NUL-terminated.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 1. Avoid explicit comparisions of pointers to `nullptr` and tests of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 presence of `optional<>` values with `.has_value()` in the predicate
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 expressions of control flow statements, but prefer them to implicit
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 conversions to `bool` when initializing `bool` variables and arguments,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 and to the use of the idiom `!!`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
212
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 #### Classes
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 1. Define POD structures with `struct`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 1. Don't use `this->` in (non-static) member functions, unless forced to
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 do so in a template member function.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 1. Define accessor and mutator member functions (implicitly) inline in the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 class, after constructors and assignments. Don't needlessly define
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 (implicit) inline member functions in classes unless they really solve a
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 performance problem.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 1. Try to make class definitions in headers concise specifications of
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 interfaces, at least to the extent that C++ allows.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 1. When copy constructors and copy assignment are not necessary,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 and move constructors/assignment is present, don't declare them and they
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 will be implicitly deleted. When neither copy nor move constructors
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 or assignments should exist for a class, explicitly `=delete` all of them.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 1. Make single-argument constructors (other than copy and move constructors)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 'explicit' unless you really want to define an implicit conversion.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
229
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 #### Pointers
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 There are many -- perhaps too many -- means of indirect addressing
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 data in this project.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 Some of these are standard C++ language and library features,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 while others are local inventions in `lib/Common`:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 * Bare pointers (`Foo *p`): these are obviously nullable, non-owning,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 undefined when uninitialized, shallowly copyable, reassignable, and often
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 not the right abstraction to use in this project.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 But they can be the right choice to represent an optional
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 non-owning reference, as in a function result.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 Use the `DEREF()` macro to convert a pointer to a reference that isn't
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 already protected by an explicit test for null.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 * References (`Foo &r`, `const Foo &r`): non-nullable, not owning,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 shallowly copyable, and not reassignable.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 References are great for invisible indirection to objects whose lifetimes are
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 broader than that of the reference.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 Take care when initializing a reference with another reference to ensure
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 that a copy is not made because only one of the references is `const`;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 this is a pernicious C++ language pitfall!
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 * Rvalue references (`Foo &&r`): These are non-nullable references
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 *with* ownership, and they are ubiquitously used for formal arguments
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 wherever appropriate.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 * `std::reference_wrapper<>`: non-nullable, not owning, shallowly
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 copyable, and (unlike bare references) reassignable, so suitable for
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 use in STL containers and for data members in classes that need to be
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 copyable or assignable.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 * `common::Reference<>`: like `std::reference_wrapper<>`, but also supports
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 move semantics, member access, and comparison for equality; suitable for use in
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 `std::variant<>`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 * `std::unique_ptr<>`: A nullable pointer with ownership, null by default,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 not copyable, reassignable.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 F18 has a helpful `Deleter<>` class template that makes `unique_ptr<>`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 easier to use with forward-referenced data types.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 * `std::shared_ptr<>`: A nullable pointer with shared ownership via reference
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 counting, null by default, shallowly copyable, reassignable, and slow.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 * `Indirection<>`: A non-nullable pointer with ownership and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 optional deep copy semantics; reassignable.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 Often better than a reference (due to ownership) or `std::unique_ptr<>`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 (due to non-nullability and copyability).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 Can be wrapped in `std::optional<>` when nullability is required.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 Usable with forward-referenced data types with some use of `extern template`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 in headers and explicit template instantiation in source files.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 * `CountedReference<>`: A nullable pointer with shared ownership via
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 reference counting, null by default, shallowly copyable, reassignable.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 Safe to use *only* when the data are private to just one
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 thread of execution.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 Used sparingly in place of `std::shared_ptr<>` only when the overhead
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 of that standard feature is prohibitive.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
278
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 A feature matrix:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
280
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 | indirection | nullable | default null | owning | reassignable | copyable | undefined type ok? |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 | ----------- | -------- | ------------ | ------ | ------------ | -------- | ------------------ |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 | `*p` | yes | no | no | yes | shallowly | yes |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 | `&r` | no | n/a | no | no | shallowly | yes |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 | `&&r` | no | n/a | yes | no | shallowly | yes |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 | `reference_wrapper<>` | no | n/a | no | yes | shallowly | yes |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 | `Reference<>` | no | n/a | no | yes | shallowly | yes |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 | `unique_ptr<>` | yes | yes | yes | yes | no | yes, with work |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 | `shared_ptr<>` | yes | yes | yes | yes | shallowly | no |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 | `Indirection<>` | no | n/a | yes | yes | optionally deeply | yes, with work |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 | `CountedReference<>` | yes | yes | yes | yes | shallowly | no |
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
292
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 ### Overall design preferences
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 Don't use dynamic solutions to solve problems that can be solved at
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 build time; don't solve build time problems by writing programs that
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 produce source code when macros and templates suffice; don't write macros
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 when templates suffice. Templates are statically typed, checked by the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 compiler, and are (or should be) visible to debuggers.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
299
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 ### Exceptions to these guidelines
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 Reasonable exceptions will be allowed; these guidelines cannot anticipate
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 all situations.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 For example, names that come from other sources might be more clear if
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 their original spellings are preserved rather than mangled to conform
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 needlessly to the conventions here, as Google's C++ style guide does
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 in a way that leads to weirdly capitalized abbreviations in names
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 like `Http`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 Consistency is one of many aspects in the pursuit of clarity,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 but not an end in itself.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
310
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 ## C++ compiler bug workarounds
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 Below is a list of workarounds for C++ compiler bugs met with f18 that, even
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 if the bugs are fixed in latest C++ compiler versions, need to be applied so
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 that all desired tool-chains can compile f18.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
315
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 ### Explicitly move noncopyable local variable into optional results
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
317
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 The following code is legal C++ but fails to compile with the
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 default Ubuntu 18.04 g++ compiler (7.4.0-1ubuntu1~18.0.4.1):
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
320
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 class CantBeCopied {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 public:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 CantBeCopied(const CantBeCopied&) = delete;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 CantBeCopied(CantBeCopied&&) = default;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 CantBeCopied() {}
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 };
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 std::optional<CantBeCopied> fooNOK() {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 CantBeCopied result;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 return result; // Legal C++, but does not compile with Ubuntu 18.04 default g++
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 std::optional<CantBeCopied> fooOK() {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 CantBeCopied result;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 return {std::move(result)}; // Compiles OK everywhere
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 ```
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 The underlying bug is actually not specific to `std::optional` but this is the most common
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 case in f18 where the issue may occur. The actual bug can be reproduced with any class `B`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 that has a perfect forwarding constructor taking `CantBeCopied` as argument:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 `template<typename CantBeCopied> B(CantBeCopied&& x) x_{std::forward<CantBeCopied>(x)} {}`.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 In such scenarios, Ubuntu 18.04 g++ fails to instantiate the move constructor
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 and to construct the returned value as it should, instead it complains about a
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 missing copy constructor.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
344
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 Local result variables do not need to and should not be explicitly moved into optionals
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 if they have a copy constructor.