Google C++ Style Guide
- -Background
C++ is one of the main development languages used by
@@ -64,10 +61,10 @@ must be large enough to justify asking all of our engineers to
remember it. The benefit is measured relative to the codebase we would
get without the rule, so a rule against a very harmful practice may
still have a small benefit if people are unlikely to do it
-anyway. This principle mostly explains the rules we don’t have, rather
+anyway. This principle mostly explains the rules we don’t have, rather
than the rules we do: for example, goto
contravenes many
of the following principles, but is already vanishingly rare, so the Style
-Guide doesn’t discuss it.
+Guide doesn’t discuss it.
In general, every .cc
file should have an
associated .h
file. There are some common
-exceptions, such as unittests and
-small .cc
files containing just a
-main()
function.
.cc
files containing
+just a main()
function.
Correct use of header files can make a huge difference to the readability, size and performance of your code.
@@ -291,16 +287,16 @@ function, or template without an associated definition. Replacing an#include
with a forward
declaration can silently change the meaning of
code:
- // b.h: - struct B {}; - struct D : B {}; +If the// b.h: +struct B {}; +struct D : B {}; - // good_user.cc: - #include "b.h" - void f(B*); - void f(void*); - void test(D* x) { f(x); } // calls f(B*) -+// good_user.cc: +#include "b.h" +void f(B*); +void f(void*); +void test(D* x) { f(x); } // calls f(B*) +
#include
was replaced with forward
decls for B
and D
,
test()
would call f(void*)
.
@@ -311,7 +307,7 @@ function, or template without an associated definition.
#include
ing the header.
.h
extension), e.g. <unistd.h>
,
+ .h
extension), e.g., <unistd.h>
,
<stdlib.h>
.<algorithm>
, <cstddef>
.dir/foo.cc
and
dir2/foo2.h
are usually in the same
-directory (e.g. base/basictypes_test.cc
and
+directory (e.g., base/basictypes_test.cc
and
base/basictypes.h
), but may sometimes be in different
directories too.
With few exceptions, place code in a namespace. Namespaces
should have unique names based on the project name, and possibly
-its path. Do not use using-directives (e.g.
+its path. Do not use using-directives (e.g.,
using namespace foo
). Do not use
inline namespaces. For unnamed namespaces, see
Unnamed Namespaces and
@@ -700,7 +696,7 @@ Do not use internal linkage in .h
files.
Nonmember, Static Member, and Global Functions
Prefer placing nonmember functions in a namespace; use completely global -functions rarely. Do not use a class simply to group static functions. Static +functions rarely. Do not use a class simply to group static members. Static methods of a class should generally be closely related to instances of the class or the class's static data.
@@ -721,8 +717,8 @@ function not bound to a class instance. Such a function can be either a static member or a nonmember function. Nonmember functions should not depend on external variables, and should nearly always exist in a namespace. -Do not create classes only to group static member functions; -this is no different than just giving the function names a +Do not create classes only to group static members; +this is no different than just giving the names a common prefix, and such grouping is usually unnecessary anyway.If you define a nonmember function and it is only @@ -741,7 +737,7 @@ scope as possible, and as close to the first use as possible. This makes it easier for the reader to find the declaration and see what type the variable is and what it was initialized to. In particular, initialization should -be used instead of declaration and assignment, e.g.:
+be used instead of declaration and assignment, e.g.,:int i; i = f(); // Bad -- initialization separate from declaration. @@ -954,8 +950,8 @@ does not make an observable difference. For example: 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, since they have non-trivial destructors. Instead, consider 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 ofint
andconst + 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
int
andconst char*
). For small collections, linear search is entirely sufficient (and efficient, due to memory locality); consider using the facilities from @@ -975,7 +971,7 @@ does not make an observable difference. For example: a type that you need to define yourself, give the type a trivial destructor and aconstexpr
constructor.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. @@ -1053,7 +1049,7 @@ variables.static + it by using a function-local static pointer or reference (e.g.,
static const auto& impl = *new T(args...);
).
thread_local
variables at class or namespace scope must be
-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, thread_local
variables
at class or namespace scope must be annotated with
@@ -1147,7 +1143,7 @@ type) is expected, such as when passing an
users can define their own, by adding appropriate members to the
class definition of the source or destination type. An implicit
conversion in the source type is defined by a type conversion operator
-named after the destination type (e.g. operator
+named after the destination type (e.g.,
operator
bool()
). An implicit conversion in the destination
type is defined by a constructor that can take the source type as
its only argument (or only argument with no default value).
The explicit
keyword can be applied to a constructor
or (since C++11) a conversion operator, to ensure that it can only be
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:
class Foo {
explicit Foo(int x, double y);
@@ -1202,8 +1198,11 @@ language treats it as one as far as explicit
is concerned.
it's intended to define an implicit conversion, or the author
simply forgot to mark it.
-
explicit
in the class definition. As an
exception, copy and move constructors should not be
explicit
, since they do not perform type
-conversion. Implicit conversions can sometimes be necessary and
-appropriate for types that are designed to transparently wrap other
-types. In that case, contact
-your project leads to request
-a waiver of this rule.
+conversion.
+
+Implicit conversions can sometimes be necessary and appropriate for +types that are designed to be interchangeable, for example when objects +of two types are just different representations of the same underlying +value. In that case, contact +your project leads to request a waiver +of this rule. +
Constructors that cannot be called with a single argument
may omit explicit
. Constructors that
take a single std::initializer_list
parameter should
also omit explicit
, in order to support copy-initialization
-(e.g. MyType m = {1, 2};
).
MyType m = {1, 2};
).
Copyable and Movable Types
@@ -1256,7 +1259,7 @@ move constructor and the move-assignment operator, if they exist, or by the copy constructor and the copy-assignment operator otherwise.The copy/move constructors can be implicitly invoked by the compiler -in some situations, e.g. when passing objects by value.
+in some situations, e.g., when passing objects by value.Objects of copyable and movable types can be passed and returned by value, @@ -1397,14 +1400,12 @@ appropriate keyword for the data-type you're defining.
structs
should be used for passive objects that carry
-data, and may have associated constants, but lack any functionality
-other than access/setting the data members. All fields must be public,
-and accessed directly rather than through getter/setter methods. The
+data, and may have associated constants. All fields must be public. The
struct must not have invariants that imply relationships between
-different fields, since direct user access to those fields may break
-those invariants. Methods should not provide behavior but should only
-be used to set up the data members, e.g., constructor, destructor,
-Initialize()
, Reset()
.
If more functionality or invariants are required, a
class
is more appropriate. If in doubt, make
@@ -1535,7 +1536,7 @@ such as operator bool()
.
Operator overloading can make code more concise and
intuitive by enabling user-defined types to behave the same
as built-in types. Overloaded operators are the idiomatic names
-for certain operations (e.g. ==
, <
,
+for certain operations (e.g., ==
, <
,
=
, and <<
), and adhering to
those conventions can make user-defined types more readable
and enable them to interoperate with libraries that expect
@@ -1563,7 +1564,7 @@ creating objects of user-defined types.
Do not overload &&
, ||
,
,
(comma), or unary &
. Do not overload
-operator""
, i.e. do not introduce user-defined
+operator""
, i.e., do not introduce user-defined
literals. Do not use any such literals provided by others
(including the standard library).
const
) if necessary.
For technical
-reasons, we allow data members of a test fixture class in a .cc file to
+reasons, we allow data members of a test fixture class defined in a .cc file to
be protected
when using
Google
-Test).
private
.
Declaration Order
@@ -1682,7 +1685,7 @@ sections that would be empty. kinds of declarations together, and generally prefer the following order: types (includingtypedef
,
using
, and nested structs and classes),
-constants, factory functions, constructors, assignment
+constants, factory functions, constructors and assignment
operators, destructor, all other methods, data members.
Do not put large method definitions inline in the @@ -1694,31 +1697,41 @@ Functions for more details.
Functions
-Output Parameters
+ +Inputs and Outputs
The output of a C++ function is naturally provided via -a return value and sometimes via output parameters.
+a return value and sometimes via output parameters (or in/out parameters).Prefer using return values over output parameters: they improve readability, and often provide the same or better -performance. If output-only parameters are used, -they should appear after input parameters.
+performance.Parameters are either input to the function, output from the
-function, or both. Input parameters are usually values or
-const
references, while output and input/output
-parameters will be pointers to non-const
.
const
references,
+while required (non-nullable) output and input/output parameters should
+usually be references. Generally, use absl::optional
to represent
+optional inputs, and non-const
pointers to represent
+optional outputs.
+
+
+Avoid defining functions that require a const
reference parameter
+to outlive the call, because const
reference parameters bind
+to temporaries. Instead, find a way to eliminate the lifetime requirement
+(for example, by copying the parameter), or pass it by const
+pointer and document the non-null requirement.
+
+
When ordering function parameters, put all input-only parameters before any output parameters. In particular, do not add new parameters to the end of the function just because they are new; place new input-only parameters before -the output parameters.
- -This is not a hard-and-fast rule. Parameters that are -both input and output (often classes/structs) muddy the -waters, and, as always, consistency with related -functions may require you to bend the rule.
+the output parameters. This is not a hard-and-fast rule. Parameters that +are both input and output muddy the waters, and, as always, +consistency with related functions may require you to bend the rule. +Variadic functions may also require unusual parameter ordering.Write Short Functions
@@ -1746,65 +1759,6 @@ errors are hard to debug, or you want to use a piece of it in several different contexts, consider breaking up the function into smaller and more manageable pieces. -Reference Arguments
- -All parameters passed by lvalue reference must be labeled
-const
.
In C, if a
-function needs to modify a variable, the parameter must
-use a pointer, eg int foo(int *pval)
. In
-C++, the function can alternatively declare a reference
-parameter: int foo(int &val)
.
Defining a parameter as reference avoids ugly code like
-(*pval)++
. Necessary for some applications
-like copy constructors. Makes it clear, unlike with
-pointers, that a null pointer is not a possible
-value.
References can be confusing, as they have value syntax -but pointer semantics.
- - -Within function parameter lists all references must be
-const
:
void Foo(const std::string &in, std::string *out); -- -
In fact it is a very strong convention in Google code
-that input arguments are values or const
-references while output arguments are pointers. Input
-parameters may be const
pointers, but we
-never allow non-const
reference parameters
-except when required by convention, e.g.,
-swap()
.
However, there are some instances where using
-const T*
is preferable to const
-T&
for input parameters. For example:
-
-
- You want to pass in a null pointer. - -
- The function saves a pointer or reference to the - input. -
Remember that most of the time input
-parameters are going to be specified as const
-T&
. Using const T*
instead
-communicates to the reader that the input is somehow
-treated differently. So if you choose const
-T*
rather than const T&
, do so
-for a concrete reason; otherwise it will likely confuse
-readers by making them look for an explanation that
-doesn't exist.
Function Overloading
Use overloaded functions (including constructors) only if a @@ -1993,7 +1947,7 @@ shared, it can be transferred from one piece of code to another.
"Smart" pointers are classes that act like pointers,
-e.g. by overloading the *
and
+e.g., by overloading the *
and
->
operators. Some smart pointer types
can be used to automate ownership bookkeeping, to ensure
these responsibilities are met.
@@ -2069,7 +2023,7 @@ all copies, and the object is deleted when the last
std::shared_ptr<const Foo>
). If you
do use shared ownership, prefer to use
std::shared_ptr
.
@@ -2131,19 +2085,7 @@ you can download
Rvalue References
-Use rvalue references to:
--
-
- Define move constructors and move assignment operators. - -
- Define overload sets with - const& and && variants if you have evidence that this - provides meaningfully better performance than passing by value, - or if you're writing low-overhead generic code that needs to support - arbitrary types. Beware combinatorial overload sets, that is, seldom - overload more than one parameter. - -
- Support 'perfect forwarding' in generic code. -
Use rvalue references only in certain special cases listed below.
Rvalue references @@ -2201,23 +2143,32 @@ rules apply. Such a reference is called forwarding reference.
-You may use rvalue references to define move constructors and move
-assignment operators (as described in
-Copyable and Movable Types). See the
-C++ Primer for more information about
-move semantics and std::move
.
Do not use rvalue references (or apply the &&
+qualifier to methods), except as follows:
-
+
- You may use them to define move constructors and move assignment + operators (as described in + Copyable and Movable Types). + -
- You may use them to define
&&
-qualified methods that + logically "consume"*this
, leaving it in an unusable + or empty state. Note that this applies only to method qualifiers (which come + after the closing parenthesis of the function signature); if you want to + "consume" an ordinary function parameter, prefer to pass it by value.
- - You may use forwarding references in conjunction with
+ std::forward
, + to support perfect forwarding.
+
+ - You may use them to define pairs of overloads, such as one taking
+
Foo&&
and the other takingconst Foo&
. + Usually the preferred solution is just to pass by value, but an overloaded + pair of functions sometimes yields better performance and is sometimes + necessary in generic code that needs to support a wide variety of types. + As always: if you're writing more complicated code for the sake of + performance, make sure you have evidence that it actually helps.
+
You may use rvalue references to define pairs of overloads, one taking
-Foo&&
and the other taking const Foo&
.
-Usually the preferred solution is just to pass by value, but an overloaded pair
-of functions sometimes yields better performance and is sometimes necessary in
-generic code that needs to support a wide variety of types. As always: if
-you're writing more complicated code for the sake of performance, make sure you
-have evidence that it actually helps.
You may use forwarding references in conjunction with
-std::forward
,
-to support perfect forwarding.
Friends
@@ -2373,14 +2324,14 @@ throw any exceptions.- Specifying move constructors as
noexcept
- improves performance in some cases, e.g. + improves performance in some cases, e.g.,std::vector<T>::resize()
moves rather than copies the objects if T's move constructor isnoexcept
. - Specifying
noexcept
on a function can trigger compiler optimizations in environments where - exceptions are enabled, e.g. compiler does not have to + exceptions are enabled, e.g., compiler does not have to generate extra code for stack-unwinding, if it knows that no exceptions can be thrown due to anoexcept
specifier.
@@ -2404,7 +2355,7 @@ throw any exceptions.
- Use brace initialization to convert arithmetic types
- (e.g.
int64{x}
). This is the safest approach because code + (e.g.,int64{x}
). This is the safest approach because code will not compile if conversion can result in information loss. The syntax is also concise.
@@ -2694,7 +2646,7 @@ localization, and security hardening.
You may use noexcept
when it is useful for
performance if it accurately reflects the intended semantics
-of your function, i.e. that if an exception is somehow thrown
+of your function, i.e., that if an exception is somehow thrown
from within the function body then it represents a fatal error.
You can assume that noexcept
on move constructors
has a meaningful performance benefit. If you think
@@ -2414,19 +2365,19 @@ with
your project leads.
Prefer unconditional noexcept
if exceptions are
-completely disabled (i.e. most Google C++ environments).
+completely disabled (i.e., most Google C++ environments).
Otherwise, use conditional noexcept
specifiers
with simple conditions, in ways that evaluate false only in
the few cases where the function could potentially throw.
The tests might include type traits check on whether the
-involved operation might throw (e.g.
+involved operation might throw (e.g.,
std::is_nothrow_move_constructible
for
move-constructing objects), or on whether allocation can throw
-(e.g. absl::default_allocator_is_nothrow
for
+(e.g., absl::default_allocator_is_nothrow
for
standard default allocation). Note in many cases the only
possible cause for an exception is allocation failure (we
believe move constructors should not throw except due to
-allocation failure), and there are many applications where it’s
+allocation failure), and there are many applications where it’s
appropriate to treat memory exhaustion as a fatal error rather
than an exceptional condition that your program should attempt
to recover from. Even for other
@@ -2434,7 +2385,7 @@ potential failures you should prioritize interface simplicity
over supporting all possible exception throwing scenarios:
instead of writing a complicated noexcept
clause
that depends on whether a hash function can throw, for example,
-simply document that your component doesn’t support hash
+simply document that your component doesn’t support hash
functions throwing and make it unconditionally
noexcept
.
static_cast<float>(double_value)
, or brace
initialization for conversion of arithmetic types like
int64 y = int64{1} << 42
. Do not use
-cast formats like
-int y = (int)x
or int y = int(x)
(but the latter
-is okay when invoking a constructor of a class type).
+cast formats like (int)x
unless the cast is to
+void
. You may use cast formats like `T(x)` only when
+`T` is a class type.
C++ introduced a @@ -2564,12 +2515,13 @@ them.
The C++-style cast syntax is verbose and cumbersome.
-Do not use C-style casts. Instead, use these C++-style casts when -explicit type conversion is necessary.
+In general, do not use C-style casts. Instead, use these C++-style +casts when explicit type conversion is necessary. +
If you do use streams, avoid the stateful parts of the
streams API (other than error state), such as imbue()
,
xalloc()
, and register_callback()
.
-Use explicit formatting functions (see e.g.
+Use explicit formatting functions (see e.g.,
absl/strings
)
rather than
@@ -2712,9 +2664,8 @@ convention).
Preincrement and Predecrement
-Use prefix form (++i
) of the increment and
-decrement operators with iterators and other template
-objects.
Use the prefix form (++i
) of the increment
+and decrement operators unless you need postfix semantics.
When a variable @@ -2725,29 +2676,24 @@ whether to preincrement (decrement) or postincrement (decrement).
-When the return value is ignored, the "pre" form
-(++i
) is never less efficient than the
-"post" form (i++
), and is often more
-efficient. This is because post-increment (or decrement)
-requires a copy of i
to be made, which is
-the value of the expression. If i
is an
-iterator or other non-scalar type, copying i
-could be expensive. Since the two types of increment
-behave the same when the value is ignored, why not just
-always pre-increment?
A postfix increment/decrement expression evaluates to the value +as it was before it was modified. This can result in code that is more +compact but harder to read. The prefix form is generally more readable, is +never less efficient, and can be more efficient because it doesn't need to +make a copy of the value as it was before the operation. +
-The tradition developed, in C, of using post-increment +
The tradition developed, in C, of using post-increment, even
when the expression value is not used, especially in
for
loops. Some find post-increment easier
to read, since the "subject" (i
) precedes
the "verb" (++
), just like in English.
For simple scalar -(non-object) values there is no reason to prefer one form -and we allow either. For iterators and other template -types, use pre-increment.
+Use prefix increment/decrement, unless the code explicitly +needs the result of the postfix increment/decrement expression.
Use of const
@@ -2784,7 +2730,7 @@ functions.We strongly recommend using const
-in APIs (i.e. on function parameters, methods, and
+in APIs (i.e., on function parameters, methods, and
non-local variables) wherever it is meaningful and accurate. This
provides consistent, mostly compiler-verified documentation
of what objects an operation can mutate. Having
@@ -2808,7 +2754,7 @@ many other contexts as well. In particular:
const
unless they
alter the logical state of the object (or enable the user to modify
- that state, e.g. by returning a non-const reference, but that's
+ that state, e.g., by returning a non-const reference, but that's
rare), or they can't safely be invoked concurrently. Some variables can be declared constexpr
-to indicate the variables are true constants, i.e. fixed at
+to indicate the variables are true constants, i.e., fixed at
compilation/link time. Some functions and constructors
can be declared constexpr
which enables them
to be used in defining a constexpr
@@ -3006,7 +2952,7 @@ problems of printing, comparisons, and structure alignment.
std::ostream
.
Unfortunately, the PRI
macros are the only portable way to
- specify a conversion for the standard bitwidth typedefs (e.g.
+ specify a conversion for the standard bitwidth typedefs (e.g.,
int64_t
, uint64_t
, int32_t
,
uint32_t
, etc).
@@ -3126,7 +3072,7 @@ possible:
Exporting macros from headers (i.e. defining them in a header +
Exporting macros from headers (i.e., defining them in a header
without #undef
ing them before the end of the header)
is extremely strongly discouraged. If you do export a macro from a
header, it must have a globally unique name. To achieve this, it
@@ -3165,11 +3111,11 @@ to any particular variable, such as code that manages an
external or internal data format where a variable of an
appropriate C++ type is not convenient.
struct data; +MyStruct data; memset(&data, 0, sizeof(data));-memset(&data, 0, sizeof(Struct)); +memset(&data, 0, sizeof(MyStruct));if (raw_size < sizeof(int)) { @@ -3227,7 +3173,7 @@ auto d{42}; // d is an int, not a std::initializer_list<int> Lambda expression return types can be deduced in the same way, but this is triggered by omitting the return type, rather than by an explicitauto
. Confusingly, - trailing return type syntax for functions + trailing return type syntax for functions also usesauto
in the return-type position, but that doesn't rely on type deduction; it's just an alternate syntax for an explicit return type. @@ -3237,7 +3183,7 @@ auto d{42}; // d is an int, not a std::initializer_list<int> one or more of its parameter types. This causes the lambda's call operator to be a function template instead of an ordinary function, with a separate template parameter for eachauto
function parameter: -// Sort `vec` in increasing order +// Sort `vec` in decreasing order std::sort(vec.begin(), vec.end(), [](auto lhs, auto rhs) { return lhs > rhs; });
(These summaries omit many details and caveats; see the links for further information.)
@@ -3312,12 +3259,12 @@ auto i = y.Find(key); inconvenience of writing an explicit type. When judging whether the code is clearer, keep in mind that your readers are not necessarily on your team, or familiar with your project, so types that you and - your reviewer experience as as unnecessary clutter will very often + your reviewer experience as unnecessary clutter will very often provide useful information to others. For example, you can assume that the return type ofmake_unique<Foo>()
is obvious,
but the return type of MyWidgetFactory()
probably isn't.
- These principles applies to all forms of type deduction, but the +
These principles apply to all forms of type deduction, but the details vary, as described in the following sections.
Function template argument deduction
@@ -3339,7 +3286,7 @@ auto i = y.Find(key); absl::flat_hash_map<std::string, std::unique_ptr<WidgetWithBellsAndWhistles>>::const_iterator it = my_map_.find(key); -std::array<int, 0> numbers = {4, 8, 15, 16, 23, 42}; +std::array<int, 6> numbers = {4, 8, 15, 16, 23, 42};auto widget_ptr = absl::make_unique<WidgetWithBellsAndWhistles>(arg1, arg2); auto it = my_map_.find(key); @@ -3386,7 +3333,7 @@ if (it != my_map_.end()) { type will almost always be clearer unless the lambda is explicitly called very close to where it's defined (so that the reader can easily see both), or the lambda is passed to an interface so well-known that it's - obvious what arguments it will eventually be called with (e.g. + obvious what arguments it will eventually be called with (e.g., thestd::sort
example above).Lambda init captures
@@ -3476,6 +3423,52 @@ array(T, U...) -> std::array<T, 1 + sizeof...(U)>;Uses of CTAD must also follow the general rules on Type deduction.
+Designated initializers
+ +Use designated initializers only in their C++20-compliant form.
+ + ++ Designated initializers are a syntax that allows for initializing an + aggregate ("plain old struct") by naming its fields explicitly: +
struct Point { + float x = 0.0; + float y = 0.0; + float z = 0.0; + }; + + Point p = { + .x = 1.0, + .y = 2.0, + // z will be 0.0 + };+ The explicitly listed fields will be initialized as specified, and others + will be initialized in the same way they would be in a traditional aggregate + initialization expression likePoint{1.0, 2.0}
. + + +Designated initializers can make for convenient and highly readable +aggregate expressions, especially for structs with less straightforward +ordering of fields than the
+ + +Point
example above.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 +into the draft C++ standard. They are on track for publishing in C++20.
+ +The rules in the draft C++ standard are stricter than in C and compiler +extensions, requiring that the designated initializers appear in the same order +as the fields appear in the struct definition. So in the example above it is +legal according to draft C++20 to initialize
+ + +x
and then +z
, but noty
and thenx
.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 +fields appear in the struct definition.
+ + +Lambda expressions
Use lambda expressions where appropriate. Prefer explicit captures @@ -3567,7 +3560,7 @@ std::sort(indices.begin(), indices.end(), [&](int a, int b) { initializers), but they look nothing like any other variable declaration syntax in C++. In particular, there's no place for the variable's type, or even an
auto
placeholder (although init captures can - indicate it indirectly, e.g. with a cast). This can make it difficult to + indicate it indirectly, e.g., with a cast). This can make it difficult to even recognize them as declarations.
You can use std::hash
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 std::hash
-does not support, consider using legacy hash containers (e.g.
+does not support, consider using legacy hash containers (e.g.,
hash_map
) for now; they use a different default hasher,
which is unaffected by this prohibition.
If you want to use the standard hash containers anyway, you will -need to specify a custom hasher for the key type, e.g.
+need to specify a custom hasher for the key type, e.g.,std::unordered_map<MyKeyType, Value, MyKeyTypeHasher> my_map;
Consult with the type's owners to see if there is an existing hasher @@ -3879,7 +3872,7 @@ using a new customization mechanism that doesn't have the drawbacks of
As with Boost, some modern C++ extensions encourage coding practices that hamper -readability—for example by removing +readability—for example by removing checked redundancy (such as type names) that may be helpful to readers, or by encouraging template metaprogramming. Other extensions duplicate functionality @@ -3917,9 +3910,8 @@ guide, the following C++ features may not be used:
Compilers support various extensions that are not part of standard C++. Such
extensions include GCC's __attribute__
, intrinsic functions such
- as __builtin_prefetch
, designated initializers (e.g.
- Foo f = {.field = 3}
), inline assembly, __COUNTER__
,
- __PRETTY_FUNCTION__
, compound statement expressions (e.g.
+ as __builtin_prefetch
, inline assembly, __COUNTER__
,
+ __PRETTY_FUNCTION__
, compound statement expressions (e.g.,
foo = ({ int x; Bar(&x); x })
, variable-length arrays and
alloca()
, and the "Elvis Operator"
a?:b
.
- Nonstandard extensions may provide useful features that do not exist - in standard C++. For example, some people think that designated - initializers are more readable than standard C++ features like - constructors. + in standard C++.
namespace mynamespace { // Bad: none of these say how they should be used. -using DataPoint = foo::Bar*; -using std::unordered_set; // Bad: just for local convenience -using std::hash; // Bad: just for local convenience +using DataPoint = ::foo::Bar*; +using ::std::unordered_set; // Bad: just for local convenience +using ::std::hash; // Bad: just for local convenience typedef unordered_set<DataPoint, hash<DataPoint>, DataPointComparator> TimeSeries; } // namespace mynamespace@@ -4034,7 +4024,7 @@ typedef unordered_set<DataPoint, hash<DataPoint>, DataPointComparator&g classes, explicitly marked internal namespaces, and in .cc files:
// In a .cc file -using foo::Bar; +using ::foo::Bar;
Naming
@@ -4112,10 +4102,13 @@ but within the scope of a class, it's likely too vague. template parameter.For the purposes of the naming rules below, a "word" is anything that you
-would write in English without internal spaces. This includes abbreviations and
-acronyms; e.g., for "camel
-case" or "Pascal case," in which the first letter of each word is
-capitalized, use a name like StartRpc()
, not
+would write in English without internal spaces. This includes abbreviations,
+such as acronyms and initialisms. For names written in mixed case (also
+sometimes referred to as
+"camel case" or
+"Pascal case"), in
+which the first letter of each word is capitalized, prefer to capitalize
+abbreviations as single words, e.g., StartRpc()
rather than
StartRPC()
.
Template parameters should follow the naming style for their
@@ -4163,8 +4156,8 @@ of files called, e.g., foo_bar.h
and
letter for each new word, with no underscores:
MyExcitingClass
, MyExcitingEnum
.
The names of all types — classes, structs, type aliases, -enums, and type template parameters — have the same naming convention. +
The names of all types — classes, structs, type aliases, +enums, and type template parameters — have the same naming convention. Type names should start with a capital letter and have a capital letter for each new word. No underscores. For example:
@@ -4180,7 +4173,7 @@ typedef hash_map<UrlTableProperties *, std::string> PropertiesMap; using PropertiesMap = hash_map<UrlTableProperties *, std::string>; // enums -enum UrlTableErrors { ... +enum class UrlTableError { ...Variable Names
@@ -4244,10 +4237,10 @@ where capitalization cannot be used for separation. For example: const int kAndroid8_0_0 = 24; // Android 8.0.0 -All such variables with static storage duration (i.e. statics and globals, +
All such variables with static storage duration (i.e., statics and globals, see Storage Duration for details) should be named this way. This -convention is optional for variables of other storage classes, e.g. automatic +convention is optional for variables of other storage classes, e.g., automatic variables, otherwise the usual variable naming rules apply.
Function Names
@@ -4312,25 +4305,20 @@ infrobber.h
)
Enumerator Names
-Enumerators (for both scoped and unscoped enums) should be named either like
-constants or like
-macros: either kEnumName
or
+
Enumerators (for both scoped and unscoped enums) should be named like
+constants, not like
+macros. That is, use kEnumName
not
ENUM_NAME
.
Preferably, the individual enumerators should be named
-like constants. However, it
-is also acceptable to name them like
-macros. The enumeration name,
-UrlTableErrors
(and
-AlternateUrlTableErrors
), is a type, and
-therefore mixed case.
enum UrlTableErrors { + +enum class UrlTableError { kOk = 0, - kErrorOutOfMemory, - kErrorMalformedInput, + kOutOfMemory, + kMalformedInput, }; -enum AlternateUrlTableErrors { ++enum class AlternateUrlTableError { OK = 0, OUT_OF_MEMORY = 1, MALFORMED_INPUT = 2, @@ -4341,10 +4329,8 @@ enum AlternateUrlTableErrors { like macros. This caused problems with name collisions between enum values and macros. Hence, the change to prefer constant-style naming -was put in place. New code should prefer constant-style -naming if possible. However, there is no reason to change -old code to use constant-style names, unless the old -names are actually causing a compile-time problem. +was put in place. New code should use constant-style +naming. @@ -4398,7 +4384,7 @@ names that you must then explain through comments.When writing your comments, write for your audience: the next contributor who will need to -understand your code. Be generous — the next +understand your code. Be generous — the next one may be you!
Comment Style
@@ -4452,8 +4438,9 @@ not at the file level.Class Comments
-Every non-obvious class declaration should have an accompanying -comment that describes what it is for and how it should be used.
+Every non-obvious class or struct declaration should have an +accompanying comment that describes what it is for and how it should +be used.
// Iterates over the contents of a GargantuanTable. // Example: @@ -4477,7 +4464,7 @@ surrounding multithreaded use.The class comment is often a good place for a small example code snippet demonstrating a simple and focused usage of the class.
-When sufficiently separated (e.g.
.h
and.cc
+When sufficiently separated (e.g.,
@@ -4493,7 +4480,7 @@ operation..h
and.cc
files), comments describing the use of the class should go together with its interface definition; comments about the class operation and implementation should accompany the implementation of the class's methods.Almost every function declaration should have comments immediately 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 -obvious (e.g. simple accessors for obvious properties of the +obvious (e.g., simple accessors for obvious properties of the class). These comments should open with descriptive verbs in the indicative mood ("Opens the file") rather than verbs in the imperative ("Open the file"). The comment describes the function; it does not @@ -4653,7 +4640,7 @@ the code is doing, and comments that mention that an error has already been logged when the function returns.
-Function Argument Comments
+Function Argument Comments
When the meaning of a function argument is nonobvious, consider one of the following remedies:
@@ -4777,7 +4764,7 @@ name that is given.@@ -4846,7 +4833,7 @@ can easily show longer lines.// TODO(kl@gmail.com): Use a "*" here for concatenation operator. // TODO(Zeke) change this to use relations. -// TODO(bug 12345): remove the "Last visitors" feature +// TODO(bug 12345): remove the "Last visitors" feature.
- a comment line which is not feasible to split without harming - 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.
- a raw-string literal with content that exceeds 80 characters. Except for
@@ -4878,7 +4865,7 @@ understood by most tools able to handle more than just
ASCII.
Hex encoding is also OK, and encouraged where it -enhances readability — for example, +enhances readability — for example,
"\xEF\xBB\xBF"
, or, even more simply,u8"\uFEFF"
, is the Unicode zero-width no-break space character, which would be invisible if @@ -5138,7 +5125,7 @@ my_widget.Transform(x1, x2, x3,Format a braced initializer list exactly like you would format a function call in its place.
-If the braced list follows a name (e.g. a type or +
If the braced list follows a name (e.g., a type or variable name), format as if the
@@ -5172,19 +5159,10 @@ MyType m = { // Here, you could also break before {.{}
were the parentheses of a function call with that name. If there is no name, assume a zero-length name.Conditionals
-Prefer no spaces inside parentheses. The
- -if
-andelse
keywords belong on separate lines.There are two acceptable formats for a basic -conditional statement. One includes spaces between the -parentheses and the condition, and one does not.
- -The most common form is without spaces. Either is -fine, but be consistent. If you are modifying a -file, use the format that is already present. If you are -writing new code, use the format that the other files in -that directory or project use. If in doubt and you have -no personal preference, do not add the spaces.
+The
if
andelse
keywords belong on separate lines. + There should be a space between theif
and the open parenthesis, + and between the close parenthesis and the curly brace (if any), but no space + between the parentheses and the condition.if (condition) { // no spaces inside parentheses ... // 2 space indent. @@ -5195,22 +5173,8 @@ no personal preference, do not add the spaces. }
-If you prefer you may add spaces inside the -parentheses:
- -if ( condition ) { // spaces inside parentheses - rare - ... // 2 space indent. -} else { // The else goes on the same line as the closing brace. - ... -} -
- -Note that in all cases you must have a space between -the
-if
and the open parenthesis. You must -also have a space between the close parenthesis and the -curly brace, if you're using one.if(condition) { // Bad - space missing after IF. +if ( condition ) { // Bad - space between the parentheses and the condition if (condition){ // Bad - space missing before {. if(condition){ // Doubly bad.
@@ -5446,8 +5410,8 @@ though wrapping all operators at the beginning of the line is also allowed. Feel free to insert extra parentheses judiciously because they can be very helpful in increasing readability when used -appropriately. Also note that you should always use -the punctuation operators, such as +appropriately, but be careful about overuse. Also note that you +should always use the punctuation operators, such as&&
and~
, rather than the word operators, such asand
andcompl
. @@ -5658,13 +5622,6 @@ void foo() { // Correct. No extra indentation within namespace. } // namespace -When declaring nested namespaces, put each namespace -on its own line.
- -namespace foo { -namespace bar { -
-Horizontal Whitespace
Use of horizontal whitespace depends on location. Never put @@ -5784,10 +5741,17 @@ useful:
well help readability. - A blank line before a comment line usually helps - readability — the introduction of a new comment suggests + readability — the introduction of a new comment suggests the start of a new thought, and the blank line makes it clear that the comment goes with the following thing instead of the preceding. + +
- Blank lines immediately inside a declaration of a namespace or block of + namespaces may help readability by visually separating the load-bearing + content from the (largely non-semantic) organizational wrapper. Especially + when the first declaration inside the namespace(s) is preceded by a comment, + this becomes a special case of the previous rule, helping the comment to + "attach" to the subsequent declaration.