mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Merge pull request #650 from zetafunction/new-thingie
Update the C++ style guide.
This commit is contained in:
commit
9806df89a3
262
cppguide.html
262
cppguide.html
|
@ -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><stdint.h></code>, such as
|
<code><cstdint></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<WidgetWithBellsAndWhistles> widget_ptr =
|
<pre class="neutralcode">std::unique_ptr<WidgetWithBellsAndWhistles> widget_ptr =
|
||||||
absl::make_unique<WidgetWithBellsAndWhistles>(arg1, arg2);
|
std::make_unique<WidgetWithBellsAndWhistles>(arg1, arg2);
|
||||||
absl::flat_hash_map<std::string,
|
absl::flat_hash_map<std::string,
|
||||||
std::unique_ptr<WidgetWithBellsAndWhistles>>::const_iterator
|
std::unique_ptr<WidgetWithBellsAndWhistles>>::const_iterator
|
||||||
it = my_map_.find(key);
|
it = my_map_.find(key);
|
||||||
std::array<int, 6> numbers = {4, 8, 15, 16, 23, 42};</pre>
|
std::array<int, 6> numbers = {4, 8, 15, 16, 23, 42};</pre>
|
||||||
|
|
||||||
<pre class="goodcode">auto widget_ptr = absl::make_unique<WidgetWithBellsAndWhistles>(arg1, arg2);
|
<pre class="goodcode">auto widget_ptr = std::make_unique<WidgetWithBellsAndWhistles>(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(), [&](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 ([&]) only when the
|
<li>Use default capture by reference (<code>[&]</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>[&]</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<T></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<int, std::string></code> is a hash
|
|
||||||
map that uses <code>std::hash<int></code> to hash its keys,
|
|
||||||
whereas <code>std::unordered_map<int, std::string, MyIntHash></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<MyKeyType, Value, MyKeyTypeHasher> 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 < result->size(); ++i) {
|
|
||||||
x = (x << 8) + (*result)[i];
|
|
||||||
(*result)[i] = x >> 1;
|
|
||||||
x &= 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<int64_t>(0, mmap_budget - index_->length());
|
|
||||||
if (mmap_budget >= data_size_ && !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>
|
Loading…
Reference in New Issue
Block a user