Update C++ style guide.

- Give more explicit guidance about when angle bracket includes should
  be used.
- Expand the guidance for disallowing const reference parameters that
  outlive the call to *all* references, const or mutable; instead, these
  parameters should be pointers.
- Add a brief section about how concepts should be named

There are also additional minor formatting changes or updating
recommendations to prefer std over absl.
This commit is contained in:
Daniel Cheng 2024-02-12 11:32:35 -08:00
parent 1ec490aaef
commit 1932017345

View File

@ -414,6 +414,18 @@ should be included as:</p>
<pre>#include "base/logging.h" <pre>#include "base/logging.h"
</pre> </pre>
<p>Headers should only be included using an angle-bracketed path if the library
requires you to do so. In particular, the following headers require angle
brackets:</p>
<ul>
<li>C and C++ standard library headers (e.g. <code>&lt;stdlib.h&gt;</code>
and <code>&lt;string&gt;</code>).</li>
<li>POSIX, Linux, and Windows system headers (e.g. <code>&lt;unistd.h&gt;</code>
and <code>&lt;windows.h&gt;</code>).</li>
<li>In rare cases, third_party libraries (e.g. <code>&lt;Python.h&gt;</code>).</li>
</ul>
<p>In <code><var>dir/foo</var>.cc</code> or <p>In <code><var>dir/foo</var>.cc</code> or
<code><var>dir/foo_test</var>.cc</code>, whose main <code><var>dir/foo_test</var>.cc</code>, whose main
purpose is to implement or test the stuff in purpose is to implement or test the stuff in
@ -425,9 +437,9 @@ as follows:</p>
<li>A blank line</li> <li>A blank line</li>
<li>C system headers (more precisely: headers in angle brackets with the <li>C system headers, and any other headers in angle brackets with the
<code>.h</code> extension), e.g., <code>&lt;unistd.h&gt;</code>, <code>.h</code> extension, e.g., <code>&lt;unistd.h&gt;</code>,
<code>&lt;stdlib.h&gt;</code>.</li> <code>&lt;stdlib.h&gt;</code>, <code>&lt;Python.h&gt;</code>.</li>
<li>A blank line</li> <li>A blank line</li>
@ -663,9 +675,9 @@ namespace baz = ::foo::bar::baz;
<pre>// Shorten access to some commonly used names (in a .h file). <pre>// Shorten access to some commonly used names (in a .h file).
namespace librarian { namespace librarian {
namespace impl { // Internal, not part of the API. namespace internal { // Internal, not part of the API.
namespace sidetable = ::pipeline_diagnostics::sidetable; namespace sidetable = ::pipeline_diagnostics::sidetable;
} // namespace impl } // namespace internal
inline void my_inline_function() { inline void my_inline_function() {
// namespace alias local to a function (or method). // namespace alias local to a function (or method).
@ -936,7 +948,7 @@ the formal language of the C++ standard. It means that the initializing
expression is a constant expression, and if the object is initialized by a expression is a constant expression, and if the object is initialized by a
constructor call, then the constructor must be specified as constructor call, then the constructor must be specified as
<code>constexpr</code>, too:</p> <code>constexpr</code>, too:</p>
<pre>struct Foo { constexpr Foo(int) {} }; <pre class="goodcode">struct Foo { constexpr Foo(int) {} };
int n = 5; // Fine, 5 is a constant expression. int n = 5; // Fine, 5 is a constant expression.
Foo x(2); // Fine, 2 is a constant expression and the chosen constructor is constexpr. Foo x(2); // Fine, 2 is a constant expression and the chosen constructor is constexpr.
@ -944,10 +956,10 @@ Foo a[] = { Foo(1), Foo(2), Foo(3) }; // Fine</pre>
<p>Constant initialization is always allowed. Constant initialization of <p>Constant initialization is always allowed. Constant initialization of
static storage duration variables should be marked with <code>constexpr</code> static storage duration variables should be marked with <code>constexpr</code>
or <code>constinit</code></p>. or <code>constinit</code>.
Any non-local static storage Any non-local static storage
duration variable that is not so marked should be presumed to have duration variable that is not so marked should be presumed to have
dynamic initialization, and reviewed very carefully. dynamic initialization, and reviewed very carefully.</p>
<p>By contrast, the following initializations are problematic:</p> <p>By contrast, the following initializations are problematic:</p>
@ -1017,10 +1029,8 @@ does not make an observable difference. For example:</p>
<p><code>thread_local</code> variables that aren't declared inside a function <p><code>thread_local</code> variables that aren't declared inside a function
must be initialized with a true compile-time constant, must be initialized with a true compile-time constant,
and this must be enforced by using the and this must be enforced by using the
<a href="https://en.cppreference.com/w/cpp/language/constinit">
<code>constinit</code></a>
<a href="https://github.com/abseil/abseil-cpp/blob/master/absl/base/attributes.h">
<code>ABSL_CONST_INIT</code></a>
attribute. Prefer 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>
@ -1093,13 +1103,11 @@ get a particularly hard to diagnose use-after-free.</p>
initialized with a true compile-time constant (i.e., they must have no initialized with a true compile-time constant (i.e., they must have no
dynamic initialization). To enforce this, <code>thread_local</code> variables dynamic initialization). To enforce this, <code>thread_local</code> variables
at class or namespace scope must be annotated with at class or namespace scope must be annotated with
<a href="https://en.cppreference.com/w/cpp/language/constinit">
<code>constinit</code></a>
<a href="https://github.com/abseil/abseil-cpp/blob/master/absl/base/attributes.h">
<code>ABSL_CONST_INIT</code></a>
(or <code>constexpr</code>, but that should be rare):</p> (or <code>constexpr</code>, but that should be rare):</p>
<pre> ABSL_CONST_INIT thread_local Foo foo = ...; <pre> constinit thread_local Foo foo = ...;
</pre> </pre>
<p><code>thread_local</code> variables inside a function have no initialization <p><code>thread_local</code> variables inside a function have no initialization
@ -1177,8 +1185,7 @@ for your code ,
terminating the program may be an appropriate error handling terminating the program may be an appropriate error handling
response. Otherwise, consider a factory function response. Otherwise, consider a factory function
or <code>Init()</code> method as described in or <code>Init()</code> method as described in
<a href="https://abseil.io/tips/42">TotW #42</a> <a href="https://abseil.io/tips/42">TotW #42</a>.
.
Avoid <code>Init()</code> methods on objects with Avoid <code>Init()</code> methods on objects with
no other states that affect which public methods may be called no other states that affect which public methods may be called
(semi-constructed objects of this form are particularly hard to work (semi-constructed objects of this form are particularly hard to work
@ -1445,8 +1452,6 @@ by making their constructors protected, by declaring their destructors protected
or by giving them one or more pure virtual member functions. Prefer to avoid or by giving them one or more pure virtual member functions. Prefer to avoid
deriving from concrete classes.</p> deriving from concrete classes.</p>
<h3 id="Structs_vs._Classes">Structs vs. Classes</h3> <h3 id="Structs_vs._Classes">Structs vs. Classes</h3>
<p>Use a <code>struct</code> only for passive objects that <p>Use a <code>struct</code> only for passive objects that
@ -1794,7 +1799,7 @@ improve readability, and often provide the same or better
performance.</p> performance.</p>
<p>Prefer to return by value or, failing that, return by reference. <p>Prefer to return by value or, failing that, return by reference.
Avoid returning a pointer unless it can be null.</p> Avoid returning a raw 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. Non-optional input parameters should usually be values function, or both. Non-optional input parameters should usually be values
@ -1808,10 +1813,10 @@ 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 reference parameter to outlive the call.
to outlive the call, because <code>const</code> reference parameters bind In some cases reference parameters can bind to temporaries, leading to lifetime
to temporaries. Instead, find a way to eliminate the lifetime requirement bugs. Instead, find a way to eliminate the lifetime requirement
(for example, by copying the parameter), or pass it by <code>const</code> (for example, by copying the parameter), or pass retained parameters by
pointer and document the lifetime and non-null requirements. pointer and document the lifetime and non-null requirements.
</p> </p>
@ -2255,10 +2260,10 @@ qualifier to methods), except as follows:</p>
<li>You may use them to define pairs of overloads, such as one taking <li>You may use them to define pairs of overloads, such as one taking
<code>Foo&amp;&amp;</code> and the other taking <code>const Foo&amp;</code>. <code>Foo&amp;&amp;</code> and the other taking <code>const Foo&amp;</code>.
Usually the preferred solution is just to pass by value, but an overloaded Usually the preferred solution is just to pass by value, but an overloaded
pair of functions sometimes yields better performance and is sometimes pair of functions sometimes yields better performance, for example if the
necessary in generic code that needs to support a wide variety of types. functions sometimes don't consume the input. As always: if you're writing
As always: if you're writing more complicated code for the sake of more complicated code for the sake of performance, make sure you have evidence
performance, make sure you have evidence that it actually helps.</li> that it actually helps.</li>
</ul> </ul>
<h3 id="Friends">Friends</h3> <h3 id="Friends">Friends</h3>
@ -2642,9 +2647,9 @@ casts when explicit type conversion is necessary.
including <code>void*</code>. Use this 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 dereferencing the pointer (without a cast) and issues. Also, consider dereferencing the pointer (without a cast) and
using <code>absl::bit_cast</code> to cast the resulting value.</li> using <code>std::bit_cast</code> to cast the resulting value.</li>
<li>Use <code>absl::bit_cast</code> to interpret the raw bits of a <li>Use <code>std::bit_cast</code> to interpret the raw bits of a
value using a different type of the same size (a type pun), such as value using a different type of the same size (a type pun), such as
interpreting the bits of a <code>double</code> as interpreting the bits of a <code>double</code> as
<code>int64_t</code>.</li> <code>int64_t</code>.</li>
@ -3243,8 +3248,8 @@ auto c = b; // c is an int
auto d{42}; // d is an int, not a std::initializer_list&lt;int&gt; auto d{42}; // d is an int, not a std::initializer_list&lt;int&gt;
</pre> </pre>
<code>auto</code> can be qualified with <code>const</code>, and can be <code>auto</code> can be qualified with <code>const</code>, and can be
used as part of a pointer or reference type, but it can't be used as a used as part of a pointer or reference type, and (since C++17) as a
template argument. A rare variant of this syntax uses non-type template argument. A rare variant of this syntax uses
<code>decltype(auto)</code> instead of <code>auto</code>, in which case <code>decltype(auto)</code> instead of <code>auto</code>, in which case
the deduced type is the result of applying the deduced type is the result of applying
<a href="https://en.cppreference.com/w/cpp/language/decltype"><code>decltype</code></a> <a href="https://en.cppreference.com/w/cpp/language/decltype"><code>decltype</code></a>
@ -4366,6 +4371,10 @@ using PropertiesMap = hash_map&lt;UrlTableProperties *, std::string&gt;;
enum class UrlTableError { ... enum class UrlTableError { ...
</pre> </pre>
<h3 id="Concept_Names">Concept Names</h3>
Concept names follow the same rules as <a href="#Type_Names">type names</a>.
<h3 id="Variable_Names">Variable Names</h3> <h3 id="Variable_Names">Variable Names</h3>
<p>The names of variables (including function parameters) and data members are <p>The names of variables (including function parameters) and data members are
@ -5216,7 +5225,8 @@ double d = 1248e6;
</pre> </pre>
<pre class="goodcode">float f = 1.0f; <pre class="goodcode">float f = 1.0f;
float f2 = 1; // Also OK float f2 = 1.0; // Also OK
float f3 = 1; // Also OK
long double ld = -0.5L; long double ld = -0.5L;
double d = 1248.0e6; double d = 1248.0e6;
</pre> </pre>