diff --git a/cppguide.html b/cppguide.html index b529854..eb0fe64 100644 --- a/cppguide.html +++ b/cppguide.html @@ -10,8 +10,6 @@

Google C++ Style Guide

-
-
@@ -162,6 +160,22 @@ input.

+

C++ Version

+ +

+Currently, code should target C++11, i.e., should not use C++14 or +C++17 features. The C++ version targeted by this guide will advance +(aggressively) over time.

+ +

+Code should avoid features that have been removed from +the latest language version (currently C++17), as well as the rare +cases where code has a different meaning in that latest version. +Use of some C++ features is restricted or disallowed. Do not use +non-standard extensions.

+ + +

Header Files

In general, every .cc file should have an @@ -972,10 +986,12 @@ dynamic initialization, and reviewed very carefully.

By contrast, the following initializations are problematic:

-
time_t time(time_t*);      // not constexpr!
+
// Some declarations used below.
+time_t time(time_t*);      // not constexpr!
 int f();                   // not constexpr!
 struct Bar { Bar() {} };
 
+// Problematic initializations.
 time_t m = time(nullptr);  // initializing expression not a constant expression
 Foo y(f());                // ditto
 Bar b;                     // chosen constructor Bar::Bar() not constexpr
@@ -1514,6 +1530,7 @@ functors and traits.

+

Inheritance

@@ -1522,16 +1539,14 @@ When using inheritance, make it public.

-

When a sub-class inherits from a base class, it includes the definitions -of all the data and operations that the parent base class -defines. In practice, inheritance is used in two major -ways in C++: implementation inheritance, in which actual -code is inherited by the child, and -interface inheritance, in which -only method names are inherited.

+of all the data and operations that the base class +defines. "Interface inheritance" is inheritance from a +pure abstract base class (one with no state or defined +methods); all other inheritance is "implementation +inheritance".

@@ -1553,6 +1568,14 @@ the sub-class, it can be more difficult to understand an implementation. The sub-class cannot override functions that are not virtual, so the sub-class cannot change implementation.

+ +

Multiple inheritance is especially problematic, because +it often imposes a higher performance overhead (in fact, +the performance drop from single inheritance to multiple +inheritance can often be greater than the performance +drop from ordinary to virtual dispatch), and because +it risks leading to "diamond" inheritance patterns, +which are prone to ambiguity, confusion, and outright bugs.

@@ -1585,119 +1608,9 @@ specifiers serve as documentation; if no specifier is present, the reader has to check all ancestors of the class in question to determine if the function or destructor is virtual or not.

-
-
- -

Multiple Inheritance

- -
-

Only very rarely is multiple implementation inheritance -actually useful. We allow multiple inheritance only when at -most one of the base classes has an implementation; all -other base classes must be pure -interface classes tagged with the -Interface suffix.

-
- -
- -
-

Multiple inheritance allows a sub-class to have more than -one base class. We distinguish between base classes that are -pure interfaces and those that have an -implementation.

-
- -
-

Multiple implementation inheritance may let you re-use -even more code than single inheritance (see Inheritance).

-
- -
-

Only very rarely is multiple implementation -inheritance actually useful. When multiple implementation -inheritance seems like the solution, you can usually find -a different, more explicit, and cleaner solution.

-
- -
-

Multiple inheritance is allowed only when all -superclasses, with the possible exception of the first one, -are pure interfaces. In order to -ensure that they remain pure interfaces, they must end with -the Interface suffix.

-
- -
-

There is an exception to -this rule on Windows.

-
- -
- -

Interfaces

- -
-

Classes that satisfy certain conditions are allowed, but -not required, to end with an Interface suffix.

-
- -
- -
-

A class is a pure interface if it meets the following -requirements:

- -
    -
  • It has only public pure virtual ("= - 0") methods and static methods (but see below - for destructor).
  • - -
  • It may not have non-static data members.
  • - -
  • It need not have any constructors defined. If a - constructor is provided, it must take no arguments and - it must be protected.
  • - -
  • If it is a subclass, it may only be derived from - classes that satisfy these conditions and are tagged - with the Interface suffix.
  • -
- -

An interface class can never be directly instantiated -because of the pure virtual method(s) it declares. To -make sure all implementations of the interface can be -destroyed correctly, the interface must also declare a -virtual destructor (in an exception to the first rule, -this should not be pure). See Stroustrup, The C++ -Programming Language, 3rd edition, section 12.4 -for details.

-
- -
-

Tagging a class with the Interface suffix -lets others know that they must not add implemented -methods or non static data members. This is particularly -important in the case of multiple inheritance. -Additionally, the interface concept is already -well-understood by Java programmers.

-
- -
-

The Interface suffix lengthens the class -name, which can make it harder to read and understand. -Also, the interface property may be considered an -implementation detail that shouldn't be exposed to -clients.

-
- -
-

A class may end -with Interface only if it meets the above -requirements. We do not require the converse, however: -classes that meet the above requirements are not required -to end with Interface.

+

Multiple inheritance is permitted, but multiple implementation +inheritance is strongly discouraged.

@@ -1840,7 +1753,7 @@ apply to operator overloading as well.

Access Control

-

Make data members private, unless they are +

Make classes' data members private, unless they are static const (and follow the naming convention for constants).

@@ -1848,7 +1761,7 @@ naming convention for constants).

For technical -reasons, we allow data members of a test fixture class to +reasons, we allow data members of a test fixture class in a .cc file to be protected when using @@ -1956,7 +1869,7 @@ the function into smaller and more manageable pieces.

Reference Arguments

-

All parameters passed by reference must be labeled +

All parameters passed by lvalue reference must be labeled const.

@@ -2053,6 +1966,11 @@ std::string_view identically-named function to take different arguments. It may be necessary for templatized code, and it can be convenient for Visitors.

+

Overloading based on const or ref qualification may make utility + code more usable, more efficient, or both. + + (See TotW 148 for more.) +

@@ -2065,15 +1983,13 @@ function.

-

You may overload a function when there are no semantic -differences between variants, or when the differences are -clear at the callsite.

- -

If you are overloading a function to support variable -number of arguments of the same type, consider making it -take a std::vector so that the user can use an -initializer list - to specify the arguments.

+

You may overload a function when there are no semantic differences +between variants. These overloads may vary in types, qualifiers, or +argument count. However, a reader of such a call must not need to know +which member of the overload set is chosen, only that something +from the set is being called. If you can document all entries in the +overload set with a single comment in the header, that is a good sign +that it is a well-designed overload set.

@@ -2183,7 +2099,7 @@ doubt, use overloads.

Trailing return type syntax is relatively new and it has no - analogue in C++-like languages like C and Java, so some readers may + analogue in C++-like languages such as C and Java, so some readers may find it unfamiliar.

Existing code bases have an enormous number of function declarations that aren't going to get changed to use the new syntax, @@ -2385,9 +2301,19 @@ you can download

Rvalue References

-

Use rvalue references only to define move constructors and move assignment -operators, or for perfect forwarding. -

+

Use rvalue references to:

+
@@ -2399,6 +2325,11 @@ objects. The syntax is similar to traditional reference syntax. For example, void f(string&& s); declares a function whose argument is an rvalue reference to a string.

+ +

When the token '&&' is applied to +an unqualified template argument in a function +parameter, special template argument deduction +rules apply. Such a reference is called forwarding reference.

@@ -2410,15 +2341,9 @@ rvalue reference to a string.

for example, then auto v2(std::move(v1)) will probably just result in some simple pointer manipulation instead of copying a large amount of data. - In some cases this can result in a major performance + In many cases this can result in a major performance improvement. -
  • Rvalue references make it possible to write a - generic function wrapper that forwards its arguments to - another function, and works whether or not its - arguments are temporary objects. (This is sometimes called - "perfect forwarding".)
  • -
  • Rvalue references make it possible to implement types that are movable but not copyable, which can be useful for types that have no sensible definition of @@ -2428,25 +2353,45 @@ rvalue reference to a string.

  • std::move is necessary to make effective use of some standard-library types, such as std::unique_ptr.
  • + +
  • Forwarding references which + use the rvalue reference token, make it possible to write a + generic function wrapper that forwards its arguments to + another function, and works whether or not its + arguments are temporary objects and/or const. + This is called 'perfect forwarding'.
  • -

    Use rvalue references only to define move constructors and move assignment - operators (as described in Copyable and - Movable Types) and, in conjunction with std::forward, -to support perfect forwarding. You may use std::move to express -moving a value from one object to another rather than copying it.

    +

    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.

    + +

    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.

    @@ -2957,6 +2902,7 @@ end-users. Be consistent with the code around you, and with the codebase as a whole; if there's an established tool for your problem, use that tool instead. In particular, + logging libraries are usually a better choice than std::cerr or std::clog for diagnostic output, and the libraries in @@ -3467,9 +3413,8 @@ name (but upper case).

    Use 0 for integers and 0.0 for reals.

    -

    For pointers (address values), there is a choice between 0, -NULL, and nullptr. For projects that allow C++11 -features, use nullptr, as this provides type-safety.

    +

    For pointers (address values), use nullptr, as this +provides type-safety.

    For C++03 projects, prefer NULL to 0. While the values are equivalent, NULL looks more like a pointer to the @@ -3830,9 +3775,6 @@ few variables for a short lambda, where the set of captured variables is obvious at a glance. Prefer not to write long or complex lambdas with default capture by value. -

  • Keep unnamed lambdas short. If a lambda body is more than -maybe five lines long, prefer to give the lambda a name, or to -use a named function instead of a lambda.
  • Specify the return type of the lambda explicitly if that will make it more obvious to readers, as with auto.
  • @@ -4147,7 +4089,7 @@ libraries.

    -

    C++11 was the official standard until august 2014, and +

    C++11 was the official standard until 2014, and is supported by most C++ compilers. It standardizes some common C++ extensions that we use already, allows shorthands for some operations, and has some performance @@ -4200,10 +4142,6 @@ guide, the following C++11 features may not be used:

    <fenv.h> headers, because many compilers do not support those features reliably. -
  • Ref-qualifiers on member functions, such as void X::Foo() - & or void X::Foo() &&, because of concerns - that they're an overly obscure feature.
  • - @@ -4412,9 +4350,9 @@ template parameter.

    For some symbols, this style guide recommends names to start with a capital letter and to have a capital letter for each new word (a.k.a. "Camel Case" -or "Pascal case"). When abbreviations appear in such names, prefer to -capitalize the abbreviations as single words (i.e. StartRpc(), -not StartRPC()).

    +or "Pascal case"). When abbreviations or acronyms appear in such +names, prefer to capitalize the abbreviations or acronyms as single words (i.e +StartRpc(), not StartRPC()).

    Template parameters should follow the naming style for their category: type template parameters should follow the rules for @@ -4461,10 +4399,6 @@ of files called, e.g., foo_bar.h and foo_bar.cc, defining a class called FooBar.

    -

    Inline functions must be in a .h file. If -your inline functions are very short, they should go -directly into your .h file.

    -

    Type Names

    @@ -4562,10 +4496,12 @@ versus a class.

    Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed - by mixed case. For example:

    + by mixed case. Underscores can be used as separators in the rare cases + where capitalization cannot be used for separation. For example:

    const int kDaysInAWeek = 7;
    +const int kAndroid8_0_0 = 24;  // Android 8.0.0
     
    @@ -5018,7 +4954,7 @@ non-obvious, interesting, or important parts of your code.

    Tricky or complicated code blocks should have comments before them. Example:

    -
    // Divide result by two, taking into account that x
    +
    // Divides 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];
    @@ -5061,7 +4997,7 @@ std::vector<string> list{
     DoSomething(); /* For trailing block comments, one space is fine. */
     
    -

    Function Argument Comments

    +

    Function Argument Comments

    When the meaning of a function argument is nonobvious, consider one of the following remedies:

    @@ -5309,22 +5245,23 @@ can easily show longer lines.

    80 characters is the maximum.

    -

    Comment lines can be longer than 80 -characters if it is not feasible to split them without -harming 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 line may exceed 80 characters if it is

    -

    A raw-string literal may have content -that exceeds 80 characters. Except for test code, such literals -should appear near the top of a file.

    +
      +
    • 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 + contains an example command or a literal URL longer than 80 characters.
    • -

      An #include statement with a -long path may exceed 80 columns.

      +
    • a raw-string literal with content that exceeds 80 characters. Except for + test code, such literals should appear near the top of a file.
    • + +
    • an include statement.
    • + +
    • a header guard
    • + +
    • a using-declaration
    • +
    -

    You needn't be concerned about -header guards that exceed -the maximum length.

    @@ -6316,29 +6253,33 @@ std::vector<char *> x;
    -

    This is more a principle than a rule: don't use blank -lines when you don't have to. In particular, don't put -more than one or two blank lines between functions, -resist starting functions with a blank line, don't end -functions with a blank line, and be discriminating with -your use of blank lines inside functions.

    +

    This is more a principle than a rule: don't use blank lines when +you don't have to. In particular, don't put more than one or two blank +lines between functions, resist starting functions with a blank line, +don't end functions with a blank line, and be sparing with your use of +blank lines. A blank line within a block of code serves like a +paragraph break in prose: visually separating two thoughts.

    -

    The basic principle is: The more code that fits on one -screen, the easier it is to follow and understand the -control flow of the program. Of course, readability can -suffer from code being too dense as well as too spread -out, so use your judgement. But in general, minimize use -of vertical whitespace.

    +

    The basic principle is: The more code that fits on one screen, the +easier it is to follow and understand the control flow of the +program. Use whitespace purposefully to provide separation in that +flow.

    Some rules of thumb to help when blank lines may be useful: