mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
Update C++ style guide.
- Reword guidance for definitions of inline functions and templates. - Capitalize the first letter of various comments. - Update command-line flag reference to use absl flags. - Improve braced-initialization example for 64-bit constants. - Delete C++03 guidance for NULL. - Clarify wording around wrapping of string literals. - Use C++17 [[fallthrough]] instead of ABSL_FALLTHROUGH.
This commit is contained in:
parent
2eb7e16647
commit
93c7bd88c6
155
cppguide.html
155
cppguide.html
|
@ -204,19 +204,15 @@ header. Specifically, a header should
|
||||||
have <a href="#The__define_Guard">header guards</a> and include all
|
have <a href="#The__define_Guard">header guards</a> and include all
|
||||||
other headers it needs.</p>
|
other headers it needs.</p>
|
||||||
|
|
||||||
<p>Prefer placing the definitions for template and inline functions in
|
<p>When a header declares inline functions or templates that clients of the
|
||||||
the same file as their declarations. The definitions of these
|
header will instantiate, the inline functions and templates must also have
|
||||||
constructs must be included into every <code>.cc</code> file that uses
|
definitions in the header, either directly or in files it includes. Do not move
|
||||||
them, or the program may fail to link in some build configurations. If
|
these definitions to separately included header (<code>-inl.h</code>) files;
|
||||||
declarations and definitions are in different files, including the
|
this practice was common in the past, but is no longer allowed. When all
|
||||||
former should transitively include the latter. Do not move these
|
instantiations of a template occur in one <code>.cc</code> file, either because
|
||||||
definitions to separately included header files (<code>-inl.h</code>);
|
they're <a href="https://en.cppreference.com/w/cpp/language/class_template#Explicit_instantiation">
|
||||||
this practice was common in the past, but is no longer allowed.</p>
|
explicit</a> or because the definition is accessible to only
|
||||||
|
the <code>.cc</code> file, the template definition can be kept in that file.</p>
|
||||||
<p>As an exception, a template that is explicitly instantiated for
|
|
||||||
all relevant sets of template arguments, or that is a private
|
|
||||||
implementation detail of a class, is allowed to be defined in the one
|
|
||||||
and only <code>.cc</code> file that instantiates the template.</p>
|
|
||||||
|
|
||||||
<p>There are rare cases where a file designed to be included is not
|
<p>There are rare cases where a file designed to be included is not
|
||||||
self-contained. These are typically intended to be included at unusual
|
self-contained. These are typically intended to be included at unusual
|
||||||
|
@ -331,7 +327,7 @@ struct D : B {};
|
||||||
#include "b.h"
|
#include "b.h"
|
||||||
void f(B*);
|
void f(B*);
|
||||||
void f(void*);
|
void f(void*);
|
||||||
void test(D* x) { f(x); } // calls f(B*)
|
void test(D* x) { f(x); } // Calls f(B*)
|
||||||
</pre>
|
</pre>
|
||||||
If the <code>#include</code> was replaced with forward
|
If the <code>#include</code> was replaced with forward
|
||||||
decls for <code>B</code> and <code>D</code>,
|
decls for <code>B</code> and <code>D</code>,
|
||||||
|
@ -492,8 +488,8 @@ might look like this:</p>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "base/commandlineflags.h"
|
|
||||||
#include "foo/server/bar.h"
|
#include "foo/server/bar.h"
|
||||||
|
#include "third_party/absl/flags/flag.h"
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p><b>Exception:</b></p>
|
<p><b>Exception:</b></p>
|
||||||
|
@ -618,7 +614,7 @@ void MyClass::Foo() {
|
||||||
|
|
||||||
<pre>#include "a.h"
|
<pre>#include "a.h"
|
||||||
|
|
||||||
ABSL_FLAG(bool, someflag, false, "dummy flag");
|
ABSL_FLAG(bool, someflag, false, "a flag");
|
||||||
|
|
||||||
namespace mynamespace {
|
namespace mynamespace {
|
||||||
|
|
||||||
|
@ -869,26 +865,26 @@ objects with static storage duration if they are trivially destructible.
|
||||||
Fundamental types (like pointers and <code>int</code>) are trivially
|
Fundamental types (like pointers and <code>int</code>) are trivially
|
||||||
destructible, as are arrays of trivially destructible types. Note that
|
destructible, as are arrays of trivially destructible types. Note that
|
||||||
variables marked with <code>constexpr</code> are trivially destructible.</p>
|
variables marked with <code>constexpr</code> are trivially destructible.</p>
|
||||||
<pre>const int kNum = 10; // allowed
|
<pre>const int kNum = 10; // Allowed
|
||||||
|
|
||||||
struct X { int n; };
|
struct X { int n; };
|
||||||
const X kX[] = {{1}, {2}, {3}}; // allowed
|
const X kX[] = {{1}, {2}, {3}}; // Allowed
|
||||||
|
|
||||||
void foo() {
|
void foo() {
|
||||||
static const char* const kMessages[] = {"hello", "world"}; // allowed
|
static const char* const kMessages[] = {"hello", "world"}; // Allowed
|
||||||
}
|
}
|
||||||
|
|
||||||
// allowed: constexpr guarantees trivial destructor
|
// Allowed: constexpr guarantees trivial destructor.
|
||||||
constexpr std::array<int, 3> kArray = {{1, 2, 3}};</pre>
|
constexpr std::array<int, 3> kArray = {1, 2, 3};</pre>
|
||||||
<pre class="badcode">// bad: non-trivial destructor
|
<pre class="badcode">// bad: non-trivial destructor
|
||||||
const std::string kFoo = "foo";
|
const std::string kFoo = "foo";
|
||||||
|
|
||||||
// bad for the same reason, even though kBar is a reference (the
|
// Bad for the same reason, even though kBar is a reference (the
|
||||||
// rule also applies to lifetime-extended temporary objects)
|
// rule also applies to lifetime-extended temporary objects).
|
||||||
const std::string& kBar = StrCat("a", "b", "c");
|
const std::string& kBar = StrCat("a", "b", "c");
|
||||||
|
|
||||||
void bar() {
|
void bar() {
|
||||||
// bad: non-trivial destructor
|
// Bad: non-trivial destructor.
|
||||||
static std::map<int, int> kData = {{1, 0}, {2, 0}, {3, 0}};
|
static std::map<int, int> kData = {{1, 0}, {2, 0}, {3, 0}};
|
||||||
}</pre>
|
}</pre>
|
||||||
|
|
||||||
|
@ -902,10 +898,10 @@ applies, though. In particular, a function-local static reference of the form
|
||||||
<p>Initialization is a more complex topic. This is because we must not only
|
<p>Initialization is a more complex topic. This is because we must not only
|
||||||
consider whether class constructors execute, but we must also consider the
|
consider whether class constructors execute, but we must also consider the
|
||||||
evaluation of the initializer:</p>
|
evaluation of the initializer:</p>
|
||||||
<pre class="neutralcode">int n = 5; // fine
|
<pre class="neutralcode">int n = 5; // Fine
|
||||||
int m = f(); // ? (depends on f)
|
int m = f(); // ? (Depends on f)
|
||||||
Foo x; // ? (depends on Foo::Foo)
|
Foo x; // ? (Depends on Foo::Foo)
|
||||||
Bar y = g(); // ? (depends on g and on Bar::Bar)
|
Bar y = g(); // ? (Depends on g and on Bar::Bar)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>All but the first statement expose us to indeterminate initialization
|
<p>All but the first statement expose us to indeterminate initialization
|
||||||
|
@ -918,9 +914,9 @@ 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>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.
|
||||||
Foo a[] = { Foo(1), Foo(2), Foo(3) }; // fine</pre>
|
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>
|
||||||
|
@ -936,22 +932,22 @@ 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>
|
||||||
|
|
||||||
<pre class="badcode">// Some declarations used below.
|
<pre class="badcode">// Some declarations used below.
|
||||||
time_t time(time_t*); // not constexpr!
|
time_t time(time_t*); // Not constexpr!
|
||||||
int f(); // not constexpr!
|
int f(); // Not constexpr!
|
||||||
struct Bar { Bar() {} };
|
struct Bar { Bar() {} };
|
||||||
|
|
||||||
// Problematic initializations.
|
// Problematic initializations.
|
||||||
time_t m = time(nullptr); // initializing expression not a constant expression
|
time_t m = time(nullptr); // Initializing expression not a constant expression.
|
||||||
Foo y(f()); // ditto
|
Foo y(f()); // Ditto
|
||||||
Bar b; // chosen constructor Bar::Bar() not constexpr</pre>
|
Bar b; // Chosen constructor Bar::Bar() not constexpr.</pre>
|
||||||
|
|
||||||
<p>Dynamic initialization of nonlocal variables is discouraged, and in general
|
<p>Dynamic initialization of nonlocal variables is discouraged, and in general
|
||||||
it is forbidden. However, we do permit it if no aspect of the program depends
|
it is forbidden. However, we do permit it if no aspect of the program depends
|
||||||
on the sequencing of this initialization with respect to all other
|
on the sequencing of this initialization with respect to all other
|
||||||
initializations. Under those restrictions, the ordering of the initialization
|
initializations. Under those restrictions, the ordering of the initialization
|
||||||
does not make an observable difference. For example:</p>
|
does not make an observable difference. For example:</p>
|
||||||
<pre>int p = getpid(); // allowed, as long as no other static variable
|
<pre>int p = getpid(); // Allowed, as long as no other static variable
|
||||||
// uses p in its own initialization</pre>
|
// uses p in its own initialization.</pre>
|
||||||
|
|
||||||
<p>Dynamic initialization of static local variables is allowed (and common).</p>
|
<p>Dynamic initialization of static local variables is allowed (and common).</p>
|
||||||
|
|
||||||
|
@ -969,19 +965,20 @@ does not make an observable difference. For example:</p>
|
||||||
<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,
|
||||||
since they have non-trivial destructors. Instead, consider a simple array of
|
since they have non-trivial destructors. Instead, consider
|
||||||
trivial types, e.g., an array of arrays of ints (for a "map from int to
|
|
||||||
|
|
||||||
|
a simple array of trivial types, e.g., an array of arrays of ints (for a "map from int to
|
||||||
int"), or an array of pairs (e.g., pairs of <code>int</code> and <code>const
|
int"), or an array of pairs (e.g., pairs of <code>int</code> and <code>const
|
||||||
char*</code>). For small collections, linear search is entirely sufficient
|
char*</code>). For small collections, linear search is entirely sufficient
|
||||||
(and efficient, due to memory locality); consider using the facilities from
|
(and efficient, due to memory locality); consider using the facilities from
|
||||||
|
|
||||||
<a href="https://github.com/abseil/abseil-cpp/blob/master/absl/algorithm/container.h">absl/algorithm/container.h</a>
|
<a href="https://github.com/abseil/abseil-cpp/blob/master/absl/algorithm/container.h">absl/algorithm/container.h</a>
|
||||||
|
|
||||||
|
|
||||||
for the standard operations. If necessary, keep the collection in sorted
|
for the standard operations. If necessary, keep the collection in sorted
|
||||||
order and use a binary search algorithm. If you do really prefer a dynamic
|
order and use a binary search algorithm.
|
||||||
container from the standard library, consider using a function-local static
|
|
||||||
pointer, as described below.</li>
|
If you do really prefer a dynamic container from the standard library, consider using
|
||||||
|
a function-local static pointer, as described below
|
||||||
|
.</li>
|
||||||
<li>Smart pointers (<code>unique_ptr</code>, <code>shared_ptr</code>): smart
|
<li>Smart pointers (<code>unique_ptr</code>, <code>shared_ptr</code>): smart
|
||||||
pointers execute cleanup during destruction and are therefore forbidden.
|
pointers execute cleanup during destruction and are therefore forbidden.
|
||||||
Consider whether your use case fits into one of the other patterns described
|
Consider whether your use case fits into one of the other patterns described
|
||||||
|
@ -991,8 +988,8 @@ does not make an observable difference. For example:</p>
|
||||||
a type that you need to define yourself, give the type a trivial destructor
|
a type that you need to define yourself, give the type a trivial destructor
|
||||||
and a <code>constexpr</code> constructor.</li>
|
and a <code>constexpr</code> constructor.</li>
|
||||||
<li>If all else fails, you can create an object dynamically and never delete
|
<li>If all else fails, you can create an object dynamically and never delete
|
||||||
it by using a function-local static pointer or reference (e.g., <code>static
|
it by using a function-local static pointer or reference (e.g.,
|
||||||
const auto& impl = *new T(args...);</code>).</li>
|
<code>static const auto& impl = *new T(args...);</code>).</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3 id="thread_local">thread_local Variables</h3>
|
<h3 id="thread_local">thread_local Variables</h3>
|
||||||
|
@ -1705,11 +1702,27 @@ 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 and type aliases (<code>typedef</code>,
|
following order:</p>
|
||||||
<code>using</code>, <code>enum</code>, nested structs and classes),
|
|
||||||
static constants, factory functions, constructors and assignment
|
<ol>
|
||||||
operators, destructor, all other member and <code>friend</code> functions,
|
<li>Types and type aliases (<code>typedef</code>, <code>using</code>,
|
||||||
data members.</p>
|
<code>enum</code>, nested structs and classes)</li>
|
||||||
|
|
||||||
|
<li>Static constants</li>
|
||||||
|
|
||||||
|
<li>Factory functions</li>
|
||||||
|
|
||||||
|
<li>Constructors and assignment operators</li>
|
||||||
|
|
||||||
|
<li>Destructor</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
All other functions (<code>static</code> and non-<code>static</code> member
|
||||||
|
functions, and <code>friend</code> functions)
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>Data members (static and non-static)</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
<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
|
||||||
|
@ -2998,7 +3011,7 @@ problems of printing, comparisons, and structure alignment.</p>
|
||||||
<p>Use <a href="#Casting">braced-initialization</a> as needed to create
|
<p>Use <a href="#Casting">braced-initialization</a> as needed to create
|
||||||
64-bit constants. For example:</p>
|
64-bit constants. For example:</p>
|
||||||
<pre>int64_t my_value{0x123456789};
|
<pre>int64_t my_value{0x123456789};
|
||||||
uint64_t my_mask{3ULL << 48};
|
uint64_t my_mask{uint64_t{3} << 48};
|
||||||
</pre>
|
</pre>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -3077,6 +3090,8 @@ possible:</p>
|
||||||
|
|
||||||
<li>Prefer not using <code>##</code> to generate
|
<li>Prefer not using <code>##</code> to generate
|
||||||
function/class/variable names.</li>
|
function/class/variable names.</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>Exporting macros from headers (i.e., defining them in a header
|
<p>Exporting macros from headers (i.e., defining them in a header
|
||||||
|
@ -3094,12 +3109,6 @@ not the <code>0</code> literal).</p>
|
||||||
<p>For pointers (address values), use <code>nullptr</code>, as this
|
<p>For pointers (address values), use <code>nullptr</code>, as this
|
||||||
provides type-safety.</p>
|
provides type-safety.</p>
|
||||||
|
|
||||||
<p>For C++03 projects, prefer <code>NULL</code> to <code>0</code>. While the
|
|
||||||
values are equivalent, <code>NULL</code> looks more like a pointer to the
|
|
||||||
reader, and some C++ compilers provide special definitions of <code>NULL</code>
|
|
||||||
which enable them to give useful warnings. Never use <code>NULL</code> for
|
|
||||||
numeric (integer or floating-point) values.</p>
|
|
||||||
|
|
||||||
<p>Use <code>'\0'</code> for the null character. Using the correct type makes
|
<p>Use <code>'\0'</code> for the null character. Using the correct type makes
|
||||||
the code more readable.</p>
|
the code more readable.</p>
|
||||||
|
|
||||||
|
@ -4759,8 +4768,20 @@ can easily show longer lines.</p>
|
||||||
readability, ease of cut and paste or auto-linking -- e.g., if a line
|
readability, ease of cut and paste or auto-linking -- e.g., if a line
|
||||||
contains an example command or a literal URL longer than 80 characters.</li>
|
contains an example command or a literal URL longer than 80 characters.</li>
|
||||||
|
|
||||||
<li>a raw-string literal with content that exceeds 80 characters. Except for
|
<li>a string literal that cannot easily be wrapped at 80 columns.
|
||||||
test code, such literals should appear near the top of a file.</li>
|
This may be because it contains URIs or other semantically-critical pieces,
|
||||||
|
or because the literal contains an embedded language, or a multiline
|
||||||
|
literal whose newlines are significant like help messages.
|
||||||
|
In these cases, breaking up the literal would
|
||||||
|
reduce readability, searchability, ability to click links, etc. Except for
|
||||||
|
test code, such literals should appear at namespace scope near the top of a
|
||||||
|
file. If a tool like Clang-Format doesn't recognize the unsplittable content,
|
||||||
|
<a href="https://clang.llvm.org/docs/ClangFormatStyleOptions.html#disabling-formatting-on-a-piece-of-code">
|
||||||
|
disable the tool</a> around the content as necessary.
|
||||||
|
<br><br>
|
||||||
|
(We must balance between usability/searchability of such literals and the
|
||||||
|
readability of the code around them.)
|
||||||
|
</li>
|
||||||
|
|
||||||
<li>an include statement.</li>
|
<li>an include statement.</li>
|
||||||
|
|
||||||
|
@ -5200,10 +5221,8 @@ case should never execute, treat this as an error. For example:
|
||||||
|
|
||||||
<p>Fall-through from one case label to
|
<p>Fall-through from one case label to
|
||||||
another must be annotated using the
|
another must be annotated using the
|
||||||
<code>ABSL_FALLTHROUGH_INTENDED;</code> macro (defined in
|
<code>[[fallthrough]];</code> attribute.
|
||||||
|
<code>[[fallthrough]];</code> should be placed at a
|
||||||
<code>absl/base/macros.h</code>).
|
|
||||||
<code>ABSL_FALLTHROUGH_INTENDED;</code> should be placed at a
|
|
||||||
point of execution where a fall-through to the next case
|
point of execution where a fall-through to the next case
|
||||||
label occurs. A common exception is consecutive case
|
label occurs. A common exception is consecutive case
|
||||||
labels without intervening code, in which case no
|
labels without intervening code, in which case no
|
||||||
|
@ -5214,14 +5233,14 @@ annotation is needed.</p>
|
||||||
case 43:
|
case 43:
|
||||||
if (dont_be_picky) {
|
if (dont_be_picky) {
|
||||||
// Use this instead of or along with annotations in comments.
|
// Use this instead of or along with annotations in comments.
|
||||||
ABSL_FALLTHROUGH_INTENDED;
|
[[fallthrough]];
|
||||||
} else {
|
} else {
|
||||||
CloseButNoCigar();
|
CloseButNoCigar();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 42:
|
case 42:
|
||||||
DoSomethingSpecial();
|
DoSomethingSpecial();
|
||||||
ABSL_FALLTHROUGH_INTENDED;
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
DoSomethingGeneric();
|
DoSomethingGeneric();
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user