Merge pull request #650 from zetafunction/new-thingie

Update the C++ style guide.
This commit is contained in:
Titus Winters 2021-10-20 12:26:38 -04:00 committed by GitHub
commit 9806df89a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -165,7 +165,8 @@ input.</p>
<h2 id="C++_Version">C++ Version</h2> <h2 id="C++_Version">C++ Version</h2>
<p>Currently, code should target C++17, i.e., should not use C++2x <p>Currently, code should target C++17, i.e., should not use C++2x
features. The C++ version targeted by this guide will advance features, with the exception of <a href="#Designated_initializers">designated
initializers</a>. The C++ version targeted by this guide will advance
(aggressively) over time.</p> (aggressively) over time.</p>
@ -441,6 +442,8 @@ as follows:</p>
<div> <div>
<li>Other libraries' <code>.h</code> files.</li> <li>Other libraries' <code>.h</code> files.</li>
<li>A blank line</li>
</div> </div>
<li> <li>
@ -957,10 +960,12 @@ does not make an observable difference. For example:</p>
<h4>Common patterns</h4> <h4>Common patterns</h4>
<ul> <ul>
<li>Global strings: if you require a global or static string constant, <li>Global strings: if you require a named global or static string constant,
consider using a simple character array, or a char pointer to the first consider using a <code>constexpr</code> variable of
element of a string literal. String literals have static storage duration <code>string_view</code>, character array, or character pointer, pointing
already and are usually sufficient.</li> to a string literal. String literals have static storage duration already
and are usually sufficient.
See <a href="https://abseil.io/tips/140">TotW #140.</a></li>
<li>Maps, sets, and other dynamic containers: if you require a static, fixed <li>Maps, sets, and other dynamic containers: if you require a static, fixed
collection, such as a set to search against or a lookup table, you cannot collection, such as a set to search against or a lookup table, you cannot
use the dynamic containers from the standard library as a static variable, use the dynamic containers from the standard library as a static variable,
@ -1003,7 +1008,7 @@ attribute. Prefer
<code>thread_local</code> over other ways of defining thread-local data.</p> <code>thread_local</code> over other ways of defining thread-local data.</p>
<p class="definition"></p> <p class="definition"></p>
<p>Starting with C++11, variables can be declared with the <p>Variables can be declared with the
<code>thread_local</code> specifier:</p> <code>thread_local</code> specifier:</p>
<pre>thread_local Foo foo = ...; <pre>thread_local Foo foo = ...;
</pre> </pre>
@ -1022,8 +1027,8 @@ thread, rather than once at program startup. This means that
other <code>thread_local</code> variables are subject to the same other <code>thread_local</code> variables are subject to the same
initialization-order issues as static variables (and more besides).</p> initialization-order issues as static variables (and more besides).</p>
<p><code>thread_local</code> variable instances are destroyed when their thread <p><code>thread_local</code> variable instances are not destroyed before their
terminates, so they do not have the destruction-order issues of static thread terminates, so they do not have the destruction-order issues of static
variables.</p> variables.</p>
<p class="pros"></p> <p class="pros"></p>
@ -1045,9 +1050,10 @@ variables.</p>
<li>The memory consumed by a <code>thread_local</code> variable scales with <li>The memory consumed by a <code>thread_local</code> variable scales with
the number of running threads (in the worst case), which can be quite large the number of running threads (in the worst case), which can be quite large
in a program.</li> in a program.</li>
<li>An ordinary class member cannot be <code>thread_local</code>.</li> <li>Non-static data members cannot be <code>thread_local</code>.</li>
<li><code>thread_local</code> may not be as efficient as certain compiler <li><code>thread_local</code> may not be as efficient as certain compiler
intrinsics.</li> intrinsics.</li>
</ul> </ul>
<p class="decision"></p> <p class="decision"></p>
@ -1164,10 +1170,10 @@ type is defined by a constructor that can take the source type as
its only argument (or only argument with no default value).</p> its only argument (or only argument with no default value).</p>
<p>The <code>explicit</code> keyword can be applied to a constructor <p>The <code>explicit</code> keyword can be applied to a constructor
or (since C++11) a conversion operator, to ensure that it can only be or a conversion operator, to ensure that it can only be
used when the destination type is explicit at the point of use, used when the destination type is explicit at the point of use,
e.g., with a cast. This applies not only to implicit conversions, but to e.g., with a cast. This applies not only to implicit conversions, but to
C++11's list initialization syntax:</p> list initialization syntax:</p>
<pre>class Foo { <pre>class Foo {
explicit Foo(int x, double y); explicit Foo(int x, double y);
... ...
@ -1395,13 +1401,10 @@ recommended that you design your class so that the default implementation of
those operations is correct. Remember to review the correctness of any those operations is correct. Remember to review the correctness of any
defaulted operations as you would any other code.</p> defaulted operations as you would any other code.</p>
<p>Due to the risk of slicing, prefer to avoid providing a public assignment <p>To eliminate the risk of slicing, prefer to make base classes abstract,
operator or copy/move constructor for a class that's by making their constructors protected, by declaring their destructors protected,
intended to be derived from (and prefer to avoid deriving from a class or by giving them one or more pure virtual member functions. Prefer to avoid
with such members). If your base class needs to be deriving from concrete classes.</p>
copyable, provide a public virtual <code>Clone()</code>
method, and a protected copy constructor that derived classes
can use to implement it.</p>
@ -1505,7 +1508,9 @@ which are prone to ambiguity, confusion, and outright bugs.</p>
<p>All inheritance should be <code>public</code>. If you <p>All inheritance should be <code>public</code>. If you
want to do private inheritance, you should be including want to do private inheritance, you should be including
an instance of the base class as a member instead.</p> an instance of the base class as a member instead. You may use
<code>final</code> on classes when you don't intend to support using
them as base classes.</p>
<p>Do not overuse implementation inheritance. Composition <p>Do not overuse implementation inheritance. Composition
is often more appropriate. Try to restrict use of is often more appropriate. Try to restrict use of
@ -1700,10 +1705,11 @@ sections that would be empty.</p>
<p>Within each section, prefer grouping similar <p>Within each section, prefer grouping similar
kinds of declarations together, and prefer the kinds of declarations together, and prefer the
following order: types (including <code>typedef</code>, following order: types and type aliases (<code>typedef</code>,
<code>using</code>, <code>enum</code>, and nested structs and classes), <code>using</code>, <code>enum</code>, nested structs and classes),
constants, factory functions, constructors and assignment static constants, factory functions, constructors and assignment
operators, destructor, all other methods, data members.</p> operators, destructor, all other member and <code>friend</code> functions,
data members.</p>
<p>Do not put large method definitions inline in the <p>Do not put large method definitions inline in the
class definition. Usually, only trivial or class definition. Usually, only trivial or
@ -1731,7 +1737,7 @@ Avoid returning a pointer unless it can be null.</p>
function, or both. Non-optional 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>std::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 and optional input/output parameters.</p> optional outputs and optional input/output parameters.</p>
@ -1890,7 +1896,7 @@ doubt, use overloads.</p>
form, the return type appears before the function name. For example:</p> form, the return type appears before the function name. For example:</p>
<pre>int foo(int x); <pre>int foo(int x);
</pre> </pre>
<p>The newer form, introduced in C++11, uses the <code>auto</code> <p>The newer form uses the <code>auto</code>
keyword before the function name and a trailing return type after keyword before the function name and a trailing return type after
the argument list. For example, the declaration above could the argument list. For example, the declaration above could
equivalently be written:</p> equivalently be written:</p>
@ -1976,7 +1982,7 @@ can be used to automate ownership bookkeeping, to ensure
these responsibilities are met. these responsibilities are met.
<a href="http://en.cppreference.com/w/cpp/memory/unique_ptr"> <a href="http://en.cppreference.com/w/cpp/memory/unique_ptr">
<code>std::unique_ptr</code></a> is a smart pointer type <code>std::unique_ptr</code></a> is a smart pointer type
introduced in C++11, which expresses exclusive ownership which expresses exclusive ownership
of a dynamically allocated object; the object is deleted of a dynamically allocated object; the object is deleted
when the <code>std::unique_ptr</code> goes out of scope. when the <code>std::unique_ptr</code> goes out of scope.
It cannot be copied, but can be <em>moved</em> to It cannot be copied, but can be <em>moved</em> to
@ -2036,7 +2042,7 @@ all copies, and the object is deleted when the last
where the resource releases take place.</li> where the resource releases take place.</li>
<li><code>std::unique_ptr</code> expresses ownership <li><code>std::unique_ptr</code> expresses ownership
transfer using C++11's move semantics, which are transfer using move semantics, which are
relatively new and may confuse some programmers.</li> relatively new and may confuse some programmers.</li>
<li>Shared ownership can be a tempting alternative to <li>Shared ownership can be a tempting alternative to
@ -2320,9 +2326,8 @@ exceptions in Google open-source projects as well.
Things would probably be different if we had to do it all Things would probably be different if we had to do it all
over again from scratch.</p> over again from scratch.</p>
<p>This prohibition also applies to the exception handling related <p>This prohibition also applies to exception handling related
features added in C++11, such as features such as <code>std::exception_ptr</code> and
<code>std::exception_ptr</code> and
<code>std::nested_exception</code>.</p> <code>std::nested_exception</code>.</p>
<p>There is an <a href="#Windows_Code">exception</a> to <p>There is an <a href="#Windows_Code">exception</a> to
@ -2546,7 +2551,14 @@ casts when explicit type conversion is necessary.
will not compile if conversion can result in information loss. The will not compile if conversion can result in information loss. The
syntax is also concise.</li> syntax is also concise.</li>
<li>Use <code>absl::implicit_cast</code>
to safely cast up a type hierarchy,
e.g., casting a <code>Foo*</code> to a
<code>SuperclassOfFoo*</code> or casting a
<code>Foo*</code> to a <code>const Foo*</code>. C++
usually does this automatically but some situations
need an explicit up-cast, such as use of the
<code>?:</code> operator.</li>
<li>Use <code>static_cast</code> as the equivalent of a C-style cast <li>Use <code>static_cast</code> as the equivalent of a C-style cast
that does value conversion, when you need to that does value conversion, when you need to
@ -2668,10 +2680,8 @@ localization, and security hardening.</p>
<p>If you do use streams, avoid the stateful parts of the <p>If you do use streams, avoid the stateful parts of the
streams API (other than error state), such as <code>imbue()</code>, streams API (other than error state), such as <code>imbue()</code>,
<code>xalloc()</code>, and <code>register_callback()</code>. <code>xalloc()</code>, and <code>register_callback()</code>.
Use explicit formatting functions (see e.g., Use explicit formatting functions (such as
<code>absl::StreamFormat()</code>) rather than
<code>absl/strings</code>)
rather than
stream manipulators or formatting flags to control formatting stream manipulators or formatting flags to control formatting
details such as number base, precision, or padding.</p> details such as number base, precision, or padding.</p>
@ -2848,7 +2858,7 @@ enable their use with <code>constexpr</code>. Do not use
is is
<code>int</code>. If a program needs a variable of a <code>int</code>. If a program needs a variable of a
different size, use a precise-width integer type from different size, use a precise-width integer type from
<code>&lt;stdint.h&gt;</code>, such as <code>&lt;cstdint&gt;</code>, such as
<code>int16_t</code>. If your variable represents a <code>int16_t</code>. If your variable represents a
value that could ever be greater than or equal to 2^31 value that could ever be greater than or equal to 2^31
(2GiB), use a 64-bit type such as <code>int64_t</code>. (2GiB), use a 64-bit type such as <code>int64_t</code>.
@ -2858,7 +2868,7 @@ calculations which may require a larger type. When in doubt,
choose a larger type.</p> choose a larger type.</p>
<p class="definition"></p> <p class="definition"></p>
<p> C++ does not specify the sizes of integer types <p> C++ does not precisely specify the sizes of integer types
like <code>int</code>. Typically people assume like <code>int</code>. Typically people assume
that <code>short</code> is 16 bits, that <code>short</code> is 16 bits,
<code>int</code> is 32 bits, <code>long</code> is 32 bits <code>int</code> is 32 bits, <code>long</code> is 32 bits
@ -3279,13 +3289,13 @@ auto i = y.Find(key);
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:</p> the reader can focus on the meaningful parts of the code:</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); std::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
it = my_map_.find(key); it = my_map_.find(key);
std::array&lt;int, 6&gt; numbers = {4, 8, 15, 16, 23, 42};</pre> std::array&lt;int, 6&gt; numbers = {4, 8, 15, 16, 23, 42};</pre>
<pre class="goodcode">auto widget_ptr = absl::make_unique&lt;WidgetWithBellsAndWhistles&gt;(arg1, arg2); <pre class="goodcode">auto widget_ptr = std::make_unique&lt;WidgetWithBellsAndWhistles&gt;(arg1, arg2);
auto it = my_map_.find(key); auto it = my_map_.find(key);
std::array numbers = {4, 8, 15, 16, 23, 42};</pre> std::array numbers = {4, 8, 15, 16, 23, 42};</pre>
@ -3450,18 +3460,18 @@ ordering of fields than the <code>Point</code> example above.</p>
<p class="cons"></p> <p class="cons"></p>
<p>While designated initializers have long been part of the C standard and <p>While designated initializers have long been part of the C standard and
supported by C++ compilers as an extension, only recently have they made it supported by C++ compilers as an extension, only recently have they made it
into the draft C++ standard. They are on track for publishing in C++20.</p> into the C++ standard, being added as part of C++20.</p>
<p>The rules in the draft C++ standard are stricter than in C and compiler <p>The rules in the C++ standard are stricter than in C and compiler extensions,
extensions, requiring that the designated initializers appear in the same order requiring that the designated initializers appear in the same order as the
as the fields appear in the struct definition. So in the example above it is fields appear in the struct definition. So in the example above, it is legal
legal according to draft C++20 to initialize <code>x</code> and then according to C++20 to initialize <code>x</code> and then <code>z</code>, but not
<code>z</code>, but not <code>y</code> and then <code>x</code>.</p> <code>y</code> and then <code>x</code>.</p>
<p class="decision"></p> <p class="decision"></p>
<p>Use designated initializers only in the form that is compatible with the <p>Use designated initializers only in the form that is compatible with the
draft C++20 standard: with initializers in the same order as the corresponding C++20 standard: with initializers in the same order as the corresponding fields
fields appear in the struct definition.</p> appear in the struct definition.</p>
@ -3549,8 +3559,8 @@ std::sort(indices.begin(), indices.end(), [&amp;](int a, int b) {
<li>Default captures by value can be misleading because they do not prevent <li>Default captures by value can be misleading because they do not prevent
dangling-pointer bugs. Capturing a pointer by value doesn't cause a deep dangling-pointer bugs. Capturing a pointer by value doesn't cause a deep
copy, so it often has the same lifetime issues as capture by reference. copy, so it often has the same lifetime issues as capture by reference.
This is especially confusing when capturing 'this' by value, since the use This is especially confusing when capturing <code>this</code> by value,
of 'this' is often implicit.</li> since the use of <code>this</code> is often implicit.</li>
<li>Captures actually declare new variables (whether or not the captures have <li>Captures actually declare new variables (whether or not the captures have
initializers), but they look nothing like any other variable declaration initializers), but they look nothing like any other variable declaration
@ -3600,14 +3610,18 @@ prefer to write:
// reference. // reference.
</pre> </pre>
</li> </li>
<li>Use default capture by reference ([&amp;]) only when the <li>Use default capture by reference (<code>[&amp;]</code>) only when
lifetime of the lambda is obviously shorter than any potential the lifetime of the lambda is obviously shorter than any potential
captures. captures.
</li> </li>
<li>Use default capture by value ([=]) only as a means of binding a <li>Use default capture by value (<code>[=]</code>) only as a means of
few variables for a short lambda, where the set of captured binding a few variables for a short lambda, where the set of captured
variables is obvious at a glance. Prefer not to write long or variables is obvious at a glance, and which does not result in
complex lambdas with default capture by value. capturing <code>this</code> implicitly. (That means that a lambda that
appears in a non-static class member function and refers to non-static
class members in its body must capture <code>this</code> explicitly or
via <code>[&amp;]</code>.) Prefer not to write long or complex lambdas
with default capture by value.
</li> </li>
<li>Use captures only to actually capture variables from the enclosing scope. <li>Use captures only to actually capture variables from the enclosing scope.
Do not use captures with initializers to introduce new names, or Do not use captures with initializers to introduce new names, or
@ -3789,76 +3803,6 @@ features to the list, so this list may be expanded in
the future.</p> the future.</p>
</div> </div>
<h3 id="std_hash">std::hash</h3>
<p>Do not define specializations of <code>std::hash</code>.</p>
<p class="definition"></p>
<p><code>std::hash&lt;T&gt;</code> is the function object that the
C++11 hash containers use to hash keys of type <code>T</code>,
unless the user explicitly specifies a different hash function. For
example, <code>std::unordered_map&lt;int, std::string&gt;</code> is a hash
map that uses <code>std::hash&lt;int&gt;</code> to hash its keys,
whereas <code>std::unordered_map&lt;int, std::string, MyIntHash&gt;</code>
uses <code>MyIntHash</code>.</p>
<p><code>std::hash</code> is defined for all integral, floating-point,
pointer, and <code>enum</code> types, as well as some standard library
types such as <code>string</code> and <code>unique_ptr</code>. Users
can enable it to work for their own types by defining specializations
of it for those types.</p>
<p class="pros"></p>
<p><code>std::hash</code> is easy to use, and simplifies the code
since you don't have to name it explicitly. Specializing
<code>std::hash</code> is the standard way of specifying how to
hash a type, so it's what outside resources will teach, and what
new engineers will expect.</p>
<p class="cons"></p>
<p><code>std::hash</code> is hard to specialize. It requires a lot
of boilerplate code, and more importantly, it combines responsibility
for identifying the hash inputs with responsibility for executing the
hashing algorithm itself. The type author has to be responsible for
the former, but the latter requires expertise that a type author
usually doesn't have, and shouldn't need. The stakes here are high
because low-quality hash functions can be security vulnerabilities,
due to the emergence of
<a href="https://emboss.github.io/blog/2012/12/14/breaking-murmur-hash-flooding-dos-reloaded/">
hash flooding attacks</a>.</p>
<p>Even for experts, <code>std::hash</code> specializations are
inordinately difficult to implement correctly for compound types,
because the implementation cannot recursively call <code>std::hash</code>
on data members. High-quality hash algorithms maintain large
amounts of internal state, and reducing that state to the
<code>size_t</code> bytes that <code>std::hash</code>
returns is usually the slowest part of the computation, so it
should not be done more than once.</p>
<p>Due to exactly that issue, <code>std::hash</code> does not work
with <code>std::pair</code> or <code>std::tuple</code>, and the
language does not allow us to extend it to support them.</p>
<p class="decision"></p>
<p>You can use <code>std::hash</code> with the types that it supports
"out of the box", but do not specialize it to support additional types.
If you need a hash table with a key type that <code>std::hash</code>
does not support, consider using legacy hash containers (e.g.,
<code>hash_map</code>) for now; they use a different default hasher,
which is unaffected by this prohibition.</p>
<p>If you want to use the standard hash containers anyway, you will
need to specify a custom hasher for the key type, e.g.,</p>
<pre>std::unordered_map&lt;MyKeyType, Value, MyKeyTypeHasher&gt; my_map;
</pre><p>
Consult with the type's owners to see if there is an existing hasher
that you can use; otherwise work with them to provide one,
or roll your own.</p>
<p>We are planning to provide a hash function that can work with any type,
using a new customization mechanism that doesn't have the drawbacks of
<code>std::hash</code>.</p>
@ -4491,6 +4435,7 @@ operation.</p>
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 class). obvious (e.g., simple accessors for obvious properties of the class).
Private methods and functions declared in `.cc` files are not exempt.
Function comments should be written with an implied subject of Function comments should be written with an implied subject of
<i>This function</i> and should start with the verb phrase; for example, <i>This function</i> and should start with the verb phrase; for example,
"Opens the file", rather than "Open the file". In general, these comments do not "Opens the file", rather than "Open the file". In general, these comments do not
@ -4603,7 +4548,7 @@ obvious. For example:</p>
<h4>Global Variables</h4> <h4>Global Variables</h4>
<p>All global variables should have a comment describing what they <p>All global variables should have a comment describing what they
are, what they are used for, and (if unclear) why it needs to be are, what they are used for, and (if unclear) why they need to be
global. For example:</p> global. For example:</p>
<pre>// The total number of test cases that we run through in this regression test. <pre>// The total number of test cases that we run through in this regression test.
@ -4618,33 +4563,7 @@ non-obvious, interesting, or important parts of your code.</p>
<h4>Explanatory Comments</h4> <h4>Explanatory Comments</h4>
<p>Tricky or complicated code blocks should have comments <p>Tricky or complicated code blocks should have comments
before them. Example:</p> before them.</p>
<pre>// Divide result by two, taking into account that x
// contains the carry from the add.
for (int i = 0; i &lt; result-&gt;size(); ++i) {
x = (x &lt;&lt; 8) + (*result)[i];
(*result)[i] = x &gt;&gt; 1;
x &amp;= 1;
}
</pre>
<h4>Line-end Comments</h4>
<p>Also, lines that are non-obvious should get a comment
at the end of the line. These end-of-line comments should
be separated from the code by 2 spaces. Example:</p>
<pre>// If we have enough memory, mmap the data portion too.
mmap_budget = max&lt;int64_t&gt;(0, mmap_budget - index_-&gt;length());
if (mmap_budget &gt;= data_size_ &amp;&amp; !MmapData(mmap_chunk_bytes, mlock))
return; // Error already logged.
</pre>
<p>Note that there are both comments that describe what
the code is doing, and comments that mention that an
error has already been logged when the function
returns.</p>
<h4 class="stylepoint_subsection" id="Function_Argument_Comments">Function Argument Comments</h4> <h4 class="stylepoint_subsection" id="Function_Argument_Comments">Function Argument Comments</h4>
@ -4662,7 +4581,8 @@ one of the following remedies:</p>
values self-describing.</li> values self-describing.</li>
<li>For functions that have several configuration options, consider <li>For functions that have several configuration options, consider
defining a single class or struct to hold all the options, defining a single class or struct to hold all the options
,
and pass an instance of that. and pass an instance of that.
This approach has several advantages. Options are referenced by name This approach has several advantages. Options are referenced by name
at the call site, which clarifies their meaning. It also reduces at the call site, which clarifies their meaning. It also reduces
@ -4882,7 +4802,7 @@ encoded as UTF-8, because that will produce incorrect
output if the compiler does not interpret the source file output if the compiler does not interpret the source file
as UTF-8. </p> as UTF-8. </p>
<p>You shouldn't use the C++11 <code>char16_t</code> and <p>You shouldn't use <code>char16_t</code> and
<code>char32_t</code> character types, since they're for <code>char32_t</code> character types, since they're for
non-UTF-8 text. For similar reasons you also shouldn't non-UTF-8 text. For similar reasons you also shouldn't
use <code>wchar_t</code> (unless you're writing code that use <code>wchar_t</code> (unless you're writing code that
@ -5630,7 +5550,9 @@ trailing whitespace at the end of a line.</p>
<h4>General</h4> <h4>General</h4>
<pre>void f(bool b) { // Open braces should always have a space before them. <pre>int i = 0; // Two spaces before end-of-line comments.
void f(bool b) { // Open braces should always have a space before them.
... ...
int i = 0; // Semicolons usually have no space before them. int i = 0; // Semicolons usually have no space before them.
// Spaces inside braces for braced-init-list are optional. If you use them, // Spaces inside braces for braced-init-list are optional. If you use them,
@ -5865,32 +5787,6 @@ occasionally need to break on Windows:</p>
<code>resource.h</code> and contain only macros, do not <code>resource.h</code> and contain only macros, do not
need to conform to these style guidelines.</li> need to conform to these style guidelines.</li>
</ul> </ul>
<h2 id="Parting_Words">Parting Words</h2>
<p>Use common sense and <em>BE CONSISTENT</em>.</p>
<p>If you are editing code, take a few minutes to look at the
code around you and determine its style. If they use spaces
around their <code>if</code> clauses, you should, too. If their
comments have little boxes of stars around them, make your
comments have little boxes of stars around them too.</p>
<p>The point of having style guidelines is to have a common
vocabulary of coding so people can concentrate on what you are
saying, rather than on how you are saying it. We present global
style rules here so people know the vocabulary. But local style
is also important. If code you add to a file looks drastically
different from the existing code around it, the discontinuity
throws readers out of their rhythm when they go to read it. Try
to avoid this.</p>
<p>OK, enough writing about writing code; the code itself is much
more interesting. Have fun!</p>
<hr>
</div> </div>
</body> </body>
</html> </html>