Merge pull request #620 from zetafunction/update-c++

Update C++ style guide.
This commit is contained in:
Titus Winters 2021-01-29 14:10:19 -05:00 committed by GitHub
commit 6e239d7f90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -343,8 +343,8 @@ void test(D* x) { f(x); } // calls f(B*)
</ul> </ul>
<p class="decision"></p> <p class="decision"></p>
Try to avoid forward declarations of entities <p>Try to avoid forward declarations of entities
defined in another project. defined in another project.</p>
<h3 id="Inline_Functions">Inline Functions</h3> <h3 id="Inline_Functions">Inline Functions</h3>
@ -512,8 +512,7 @@ should have unique names based on the project name, and possibly
its path. Do not use <i>using-directives</i> (e.g., its path. Do not use <i>using-directives</i> (e.g.,
<code>using namespace foo</code>). Do not use <code>using namespace foo</code>). Do not use
inline namespaces. For unnamed namespaces, see inline namespaces. For unnamed namespaces, see
<a href="#Unnamed_Namespaces_and_Static_Variables">Unnamed Namespaces and <a href="#Internal_Linkage">Internal Linkage</a>.
Static Variables</a>.
</p><p class="definition"></p> </p><p class="definition"></p>
<p>Namespaces subdivide the global scope <p>Namespaces subdivide the global scope
@ -674,13 +673,13 @@ inline void my_inline_function() {
</li><li>Do not use inline namespaces.</li> </li><li>Do not use inline namespaces.</li>
</ul> </ul>
<h3 id="Unnamed_Namespaces_and_Static_Variables">Unnamed Namespaces and Static <a id="Unnamed_Namespaces_and_Static_Variables"></a>
Variables</h3> <h3 id="Internal_Linkage">Internal Linkage</h3>
<p>When definitions in a <code>.cc</code> file do not need to be <p>When definitions in a <code>.cc</code> file do not need to be
referenced outside that file, place them in an unnamed referenced outside that file, give them internal linkage by placing
namespace or declare them <code>static</code>. Do not use either them in an unnamed namespace or declaring them <code>static</code>.
of these constructs in <code>.h</code> files. Do not use either of these constructs in <code>.h</code> files.
</p><p class="definition"></p> </p><p class="definition"></p>
<p>All declarations can be given internal linkage by placing them in unnamed <p>All declarations can be given internal linkage by placing them in unnamed
@ -733,7 +732,7 @@ common prefix, and such grouping is usually unnecessary anyway.</p>
<p>If you define a nonmember function and it is only <p>If you define a nonmember function and it is only
needed in its <code>.cc</code> file, use needed in its <code>.cc</code> file, use
<a href="#Unnamed_Namespaces_and_Static_Variables">internal linkage</a> to limit <a href="#Internal_Linkage">internal linkage</a> to limit
its scope.</p> its scope.</p>
<h3 id="Local_Variables">Local Variables</h3> <h3 id="Local_Variables">Local Variables</h3>
@ -1366,8 +1365,8 @@ class NotCopyableOrMovable {
}; };
</pre> </pre>
<p>These declarations/deletions can be omitted only if they are obvious: <p>These declarations/deletions can be omitted only if they are obvious:</p>
</p><ul> <ul>
<li>If the class has no <code>private</code> section, like a <li>If the class has no <code>private</code> section, like a
<a href="#Structs_vs._Classes">struct</a> or an interface-only base class, <a href="#Structs_vs._Classes">struct</a> or an interface-only base class,
then the copyability/movability can be determined by the then the copyability/movability can be determined by the
@ -1723,13 +1722,13 @@ performance.</p>
Avoid returning a pointer unless it can be null.</p> Avoid returning a pointer unless it can be null.</p>
<p>Parameters are either inputs to the function, outputs from the <p>Parameters are either inputs to the function, outputs from the
function, or both. Input parameters should usually be values function, or both. Non-optional input parameters should usually be values
or <code>const</code> references, while non-optional output and or <code>const</code> references, while non-optional output and
input/output parameters should usually be references (which cannot be null). input/output parameters should usually be references (which cannot be null).
Generally, use <code>absl::optional</code> to represent optional by-value Generally, use <code>absl::optional</code> to represent optional by-value
inputs, and use a <code>const</code> pointer when the non-optional form would inputs, and use a <code>const</code> pointer when the non-optional form would
have used a reference. Use non-<code>const</code> pointers to represent have used a reference. Use non-<code>const</code> pointers to represent
optional outputs.</p> optional outputs and optional input/output parameters.</p>
<p> <p>
Avoid defining functions that require a <code>const</code> reference parameter Avoid defining functions that require a <code>const</code> reference parameter
@ -2555,7 +2554,8 @@ casts when explicit type conversion is necessary.
<li>Use <code>reinterpret_cast</code> to do unsafe conversions of <li>Use <code>reinterpret_cast</code> to do unsafe conversions of
pointer types to and from integer and other pointer pointer types to and from integer and other pointer
types. Use this types,
including <code>void*</code>. Use this
only if you know what you are doing and you understand the aliasing only if you know what you are doing and you understand the aliasing
issues. Also, consider the alternative issues. Also, consider the alternative
<code>absl::bit_cast</code>.</li> <code>absl::bit_cast</code>.</li>
@ -2701,9 +2701,7 @@ make a copy of the value as it was before the operation.
<p class="cons"></p> <p class="cons"></p>
<p>The tradition developed, in C, of using post-increment, even <p>The tradition developed, in C, of using post-increment, even
when the expression value is not used, especially in when the expression value is not used, especially in
<code>for</code> loops. Some find post-increment easier <code>for</code> loops.</p>
to read, since the "subject" (<code>i</code>) precedes
the "verb" (<code>++</code>), just like in English.</p>
<p class="decision"></p> <p class="decision"></p>
<p>Use prefix increment/decrement, unless the code explicitly <p>Use prefix increment/decrement, unless the code explicitly
@ -3294,8 +3292,8 @@ auto i = y.Find(key);
<p>For local variables, you can use type deduction to make the code clearer <p>For local variables, you can use type deduction to make the code clearer
by eliminating type information that is obvious or irrelevant, so that by eliminating type information that is obvious or irrelevant, so that
the reader can focus on the meaningful parts of the code: the reader can focus on the meaningful parts of the code:</p>
</p><pre class="neutralcode">std::unique_ptr&lt;WidgetWithBellsAndWhistles&gt; widget_ptr = <pre class="neutralcode">std::unique_ptr&lt;WidgetWithBellsAndWhistles&gt; widget_ptr =
absl::make_unique&lt;WidgetWithBellsAndWhistles&gt;(arg1, arg2); absl::make_unique&lt;WidgetWithBellsAndWhistles&gt;(arg1, arg2);
absl::flat_hash_map&lt;std::string, absl::flat_hash_map&lt;std::string,
std::unique_ptr&lt;WidgetWithBellsAndWhistles&gt;&gt;::const_iterator std::unique_ptr&lt;WidgetWithBellsAndWhistles&gt;&gt;::const_iterator
@ -3311,17 +3309,17 @@ std::array numbers = {4, 8, 15, 16, 23, 42};</pre>
type is an iterator, and in many contexts the container type and even the type is an iterator, and in many contexts the container type and even the
key type aren't relevant, but the type of the values is probably useful. key type aren't relevant, but the type of the values is probably useful.
In such situations, it's often possible to define local variables with In such situations, it's often possible to define local variables with
explicit types that convey the relevant information: explicit types that convey the relevant information:</p>
</p><pre class="goodcode">if (auto it = my_map_.find(key); it != my_map_.end()) { <pre class="goodcode">if (auto it = my_map_.find(key); it != my_map_.end()) {
WidgetWithBellsAndWhistles&amp; widget = *it-&gt;second; WidgetWithBellsAndWhistles&amp; widget = *it-&gt;second;
// Do stuff with `widget` // Do stuff with `widget`
}</pre> }</pre>
If the type is a template instance, and the parameters are <p>If the type is a template instance, and the parameters are
boilerplate but the template itself is informative, you can use boilerplate but the template itself is informative, you can use
class template argument deduction to suppress the boilerplate. However, class template argument deduction to suppress the boilerplate. However,
cases where this actually provides a meaningful benefit are quite rare. cases where this actually provides a meaningful benefit are quite rare.
Note that class template argument deduction is also subject to a Note that class template argument deduction is also subject to a
<a href="#CTAD">separate style rule</a>. <a href="#CTAD">separate style rule</a>.</p>
<p>Do not use <code>decltype(auto)</code> if a simpler option will work, <p>Do not use <code>decltype(auto)</code> if a simpler option will work,
because it's a fairly obscure feature, so it has a high cost in code because it's a fairly obscure feature, so it has a high cost in code
@ -3373,10 +3371,10 @@ std::array numbers = {4, 8, 15, 16, 23, 42};</pre>
this may also mean the names are less recognizable to your reader than the this may also mean the names are less recognizable to your reader than the
field names. We recommend using a comment to indicate the name of the field names. We recommend using a comment to indicate the name of the
underlying field, if it doesn't match the name of the binding, using the underlying field, if it doesn't match the name of the binding, using the
same syntax as for function parameter comments: same syntax as for function parameter comments:</p>
</p><pre>auto [/*field_name1=*/ bound_name1, /*field_name2=*/ bound_name2] = ...</pre> <pre>auto [/*field_name1=*/ bound_name1, /*field_name2=*/ bound_name2] = ...</pre>
As with function parameter comments, this can enable tools to detect if <p>As with function parameter comments, this can enable tools to detect if
you get the order of the fields wrong. you get the order of the fields wrong.</p>
<h3 id="CTAD">Class Template Argument Deduction</h3> <h3 id="CTAD">Class Template Argument Deduction</h3>
@ -3387,21 +3385,21 @@ std::array numbers = {4, 8, 15, 16, 23, 42};</pre>
<p><a href="https://en.cppreference.com/w/cpp/language/class_template_argument_deduction">Class <p><a href="https://en.cppreference.com/w/cpp/language/class_template_argument_deduction">Class
template argument deduction</a> (often abbreviated "CTAD") occurs when template argument deduction</a> (often abbreviated "CTAD") occurs when
a variable is declared with a type that names a template, and the template a variable is declared with a type that names a template, and the template
argument list is not provided (not even empty angle brackets): argument list is not provided (not even empty angle brackets):</p>
</p><pre class="neutralcode">std::array a = {1, 2, 3}; // `a` is a std::array&lt;int, 3&gt;</pre> <pre class="neutralcode">std::array a = {1, 2, 3}; // `a` is a std::array&lt;int, 3&gt;</pre>
The compiler deduces the arguments from the initializer using the <p>The compiler deduces the arguments from the initializer using the
template's "deduction guides", which can be explicit or implicit. template's "deduction guides", which can be explicit or implicit.</p>
<p>Explicit deduction guides look like function declarations with trailing <p>Explicit deduction guides look like function declarations with trailing
return types, except that there's no leading <code>auto</code>, and the return types, except that there's no leading <code>auto</code>, and the
function name is the name of the template. For example, the above example function name is the name of the template. For example, the above example
relies on this deduction guide for <code>std::array</code>: relies on this deduction guide for <code>std::array</code>:</p>
</p><pre class="neutralcode">namespace std { <pre class="neutralcode">namespace std {
template &lt;class T, class... U&gt; template &lt;class T, class... U&gt;
array(T, U...) -&gt; std::array&lt;T, 1 + sizeof...(U)&gt;; array(T, U...) -&gt; std::array&lt;T, 1 + sizeof...(U)&gt;;
}</pre> }</pre>
Constructors in a primary template (as opposed to a template specialization) <p>Constructors in a primary template (as opposed to a template specialization)
also implicitly define deduction guides. also implicitly define deduction guides.</p>
<p>When you declare a variable that relies on CTAD, the compiler selects <p>When you declare a variable that relies on CTAD, the compiler selects
a deduction guide using the rules of constructor overload resolution, a deduction guide using the rules of constructor overload resolution,
@ -3443,8 +3441,8 @@ array(T, U...) -&gt; std::array&lt;T, 1 + sizeof...(U)&gt;;
<p class="definition"></p> <p class="definition"></p>
<p><a href="https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers"> <p><a href="https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers">
Designated initializers</a> are a syntax that allows for initializing an Designated initializers</a> are a syntax that allows for initializing an
aggregate ("plain old struct") by naming its fields explicitly: aggregate ("plain old struct") by naming its fields explicitly:</p>
</p><pre class="neutralcode"> struct Point { <pre class="neutralcode"> struct Point {
float x = 0.0; float x = 0.0;
float y = 0.0; float y = 0.0;
float z = 0.0; float z = 0.0;
@ -3455,9 +3453,9 @@ array(T, U...) -&gt; std::array&lt;T, 1 + sizeof...(U)&gt;;
.y = 2.0, .y = 2.0,
// z will be 0.0 // z will be 0.0
};</pre> };</pre>
The explicitly listed fields will be initialized as specified, and others <p>The explicitly listed fields will be initialized as specified, and others
will be initialized in the same way they would be in a traditional aggregate will be initialized in the same way they would be in a traditional aggregate
initialization expression like <code>Point{1.0, 2.0}</code>. initialization expression like <code>Point{1.0, 2.0}</code>.</p>
<p class="pros"></p> <p class="pros"></p>
<p>Designated initializers can make for convenient and highly readable <p>Designated initializers can make for convenient and highly readable
@ -3525,20 +3523,20 @@ std::sort(indices.begin(), indices.end(), [&amp;](int a, int b) {
<p>A variable capture can also have an explicit initializer, which can <p>A variable capture can also have an explicit initializer, which can
be used for capturing move-only variables by value, or for other situations be used for capturing move-only variables by value, or for other situations
not handled by ordinary reference or value captures: not handled by ordinary reference or value captures:</p>
</p><pre>std::unique_ptr&lt;Foo&gt; foo = ...; <pre>std::unique_ptr&lt;Foo&gt; foo = ...;
[foo = std::move(foo)] () { [foo = std::move(foo)] () {
... ...
}</pre> }</pre>
Such captures (often called "init captures" or "generalized lambda captures") <p>Such captures (often called "init captures" or "generalized lambda captures")
need not actually "capture" anything from the enclosing scope, or even have need not actually "capture" anything from the enclosing scope, or even have
a name from the enclosing scope; this syntax is a fully general way to define a name from the enclosing scope; this syntax is a fully general way to define
members of a lambda object: members of a lambda object:</p>
<pre class="neutralcode">[foo = std::vector&lt;int&gt;({1, 2, 3})] () { <pre class="neutralcode">[foo = std::vector&lt;int&gt;({1, 2, 3})] () {
... ...
}</pre> }</pre>
The type of a capture with an initializer is deduced using the same rules <p>The type of a capture with an initializer is deduced using the same rules
as <code>auto</code>. as <code>auto</code>.</p>
<p class="pros"></p> <p class="pros"></p>
<ul> <ul>
@ -3881,6 +3879,7 @@ using a new customization mechanism that doesn't have the drawbacks of
<h3 id="Other_Features"><a id="C++11">Other C++ Features</a></h3> <h3 id="Other_Features"><a id="C++11">Other C++ Features</a></h3>
<p>As with <a href="#Boost">Boost</a>, some modern C++ <p>As with <a href="#Boost">Boost</a>, some modern C++
extensions encourage coding practices that hamper extensions encourage coding practices that hamper
readability—for example by removing readability—for example by removing
@ -4013,7 +4012,7 @@ implementation retain some degree of freedom to change the alias.</p>
<pre>namespace mynamespace { <pre>namespace mynamespace {
// Used to store field measurements. DataPoint may change from Bar* to some internal type. // Used to store field measurements. DataPoint may change from Bar* to some internal type.
// Client code should treat it as an opaque pointer. // Client code should treat it as an opaque pointer.
using DataPoint = foo::Bar*; using DataPoint = ::foo::Bar*;
// A set of measurements. Just an alias for user convenience. // A set of measurements. Just an alias for user convenience.
using TimeSeries = std::unordered_set&lt;DataPoint, std::hash&lt;DataPoint&gt;, DataPointComparator&gt;; using TimeSeries = std::unordered_set&lt;DataPoint, std::hash&lt;DataPoint&gt;, DataPointComparator&gt;;
@ -4319,7 +4318,8 @@ build breaks because of name lookup rules. In particular, do not
create any nested <code>std</code> namespaces. Prefer unique project create any nested <code>std</code> namespaces. Prefer unique project
identifiers identifiers
(<code>websearch::index</code>, <code>websearch::index_util</code>) (<code>websearch::index</code>, <code>websearch::index_util</code>)
over collision-prone names like <code>websearch::util</code>.</p> over collision-prone names like <code>websearch::util</code>. Also avoid overly deep nesting
namespaces (<a href="https://abseil.io/tips/130">TotW #130</a>).</p>
<p>For <code>internal</code> namespaces, be wary of other code being <p>For <code>internal</code> namespaces, be wary of other code being
added to the same <code>internal</code> namespace causing a collision added to the same <code>internal</code> namespace causing a collision
@ -4327,7 +4327,7 @@ added to the same <code>internal</code> namespace causing a collision
collisions). In such a situation, using the filename to make a unique collisions). In such a situation, using the filename to make a unique
internal name is helpful internal name is helpful
(<code>websearch::index::frobber_internal</code> for use (<code>websearch::index::frobber_internal</code> for use
in <code>frobber.h</code>)</p> in <code>frobber.h</code>).</p>
<h3 id="Enumerator_Names">Enumerator Names</h3> <h3 id="Enumerator_Names">Enumerator Names</h3>
@ -4505,11 +4505,10 @@ operation.</p>
<p>Almost every function declaration should have comments immediately <p>Almost every function declaration should have comments immediately
preceding it that describe what the function does and how to use preceding it that describe what the function does and how to use
it. These comments may be omitted only if the function is simple and it. These comments may be omitted only if the function is simple and
obvious (e.g., simple accessors for obvious properties of the obvious (e.g., simple accessors for obvious properties of the class).
class). These comments should open with descriptive verbs in the Function comments should be written with an implied subject of
indicative mood ("Opens the file") rather than verbs in the imperative <i>This function</i> and should start with the verb phrase; for example,
("Open the file"). The comment describes the function; it does not "Opens the file", rather than "Open the file". In general, these comments do not
tell the function what to do. In general, these comments do not
describe how the function performs its task. Instead, that should be describe how the function performs its task. Instead, that should be
left to comments in the function definition.</p> left to comments in the function definition.</p>
@ -5373,22 +5372,27 @@ x = r-&gt;y;
<code>*</code> or <code>&amp;</code>.</li> <code>*</code> or <code>&amp;</code>.</li>
</ul> </ul>
<p>When declaring a pointer or reference variable or argument, you may <p>When referring to a pointer or reference (variable declarations or definitions, arguments,
place the asterisk/ampersand adjacent to either the type or the return types, template parameters, etc), you may place the space before or after the
variable name:</p> asterisk/ampersand. In the trailing-space style, the space is elided in some cases (template
parameters, etc).</p>
<pre>// These are fine, space preceding. <pre>// These are fine, space preceding.
char *c; char *c;
const std::string &amp;str; const std::string &amp;str;
int *GetPointer();
std::vector&lt;char *&gt;
// These are fine, space following. // These are fine, space following (or elided).
char* c; char* c;
const std::string&amp; str; const std::string&amp; str;
int* GetPointer();
std::vector&lt;char*&gt; // Note no space between '*' and '&gt;'
</pre> </pre>
<p>You should do this consistently within a single <p>You should do this consistently within a single
file, file.
so, when modifying an existing file, use the style in When modifying an existing file, use the style in
that file.</p> that file.</p>
It is allowed (if unusual) to declare multiple variables in the same It is allowed (if unusual) to declare multiple variables in the same