From f15e633de5b716a966504e0652fb0c85c2f4f4fb Mon Sep 17 00:00:00 2001 From: Titus Winters Date: Wed, 6 Jul 2016 12:12:21 -0400 Subject: [PATCH] Update to current. This notably includes changes for namespace naming and use of auto, as well as clarification on when comments are necessary and attribute placement. --- cppguide.html | 669 +++++++++++++++++++++++++------------------------- 1 file changed, 330 insertions(+), 339 deletions(-) diff --git a/cppguide.html b/cppguide.html index d09872d..3539e68 100644 --- a/cppguide.html +++ b/cppguide.html @@ -15,7 +15,7 @@ -

C++ is the main development language used by +

C++ is one of the main development languages used by many of Google's open-source projects. As every C++ programmer knows, the language has many powerful features, but this power brings with it complexity, which in turn can make @@ -179,36 +179,37 @@ pitfalls of using header files.

Self-contained Headers

-

Header files should be self-contained and end in .h. Files that -are meant for textual inclusion, but are not headers, should end in -.inc. Separate -inl.h headers are disallowed.

+

Header files should be self-contained (compile on their own) and +end in .h. Non-header files that are meant for inclusion +should end in .inc.

-

All header files should be self-contained. In other -words, users and refactoring tools should not have to adhere to special -conditions in order to include the header. Specifically, a -header should have header guards, -should include all other headers it needs, and should not require any -particular symbols to be defined.

+

All header files should be self-contained. Users and refactoring +tools should not have to adhere to special conditions to include the +header. Specifically, a header should +have header guards and include all +other headers it needs.

-

There are rare cases where a file is not meant to be self-contained, but -instead is meant to be textually included at a specific point in the code. -Examples are files that need to be included multiple times or -platform-specific extensions that essentially are part of other headers. Such -files should use the file extension .inc.

+

If a template or inline function is declared in a .h +file, that same header should provide its definition. The definitions +of these constructs must be included into every .cc file +that uses them, or the program may fail to link in some build +configurations. Do not move these definitions to separately included +header files (-inl.h); this practice was common in the +past, but is no longer allowed.

-

If a template or inline function is declared in a .h file, -define it in that same file. The definitions of these constructs must -be included into every .cc file that uses them, or the -program may fail to link in some build configurations. Do not move these -definitions to separate -inl.h files.

+

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 .cc file that instantiates the template.

-

As an exception, a function template that is explicitly -instantiated for all relevant sets of template arguments, or -that is a private member of a class, may -be defined in the only .cc file that -instantiates the template.

+

There are rare cases where a file is not meant to be +self-contained, but it is meant to be included at a specific point in +the code. Examples are files that need to be included multiple times +or platform-specific implementation details that are essentially part +of other self-contained headers. Such files should use the file +extension .inc.

@@ -509,7 +510,8 @@ system-specific code small and localized. Example:

With few exceptions, place code in a namespace. Namespaces should have unique names based on the project name, and possibly its path. Unnamed namespaces in .cc files are -encouraged. Do not use using-directives. Do not use +encouraged. Do not use using-directives (e.g. +using namespace foo). Do not use inline namespaces.

@@ -732,7 +734,7 @@ external resources or have significant dependencies.

-

Sometimes it is useful, or even necessary, to define a +

Sometimes it is useful to define a 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 @@ -758,7 +760,7 @@ class FooBar { } -

If you must define a nonmember function and it is only +

If you define a nonmember function and it is only needed in its .cc file, use an unnamed namespace or static linkage (eg static int Foo() @@ -1097,10 +1099,10 @@ also omit explicit, in order to support copy-initialization

Copyable and Movable Types

-

Support copying and/or moving if it makes sense for your type. -Otherwise, disable the implicitly generated special -functions that perform copies and moves.

-
+

Support copying and/or moving if these operations are clear and meaningful +for your type. Otherwise, disable the implicitly generated special functions +that perform copies and moves. +

@@ -1122,15 +1124,15 @@ in some situations, e.g. when passing objects by value.

-

Objects of copyable and movable types can be passed and returned -by value, which makes APIs simpler, safer, and more general. -Unlike when passing pointers or references, there's no risk of -confusion over ownership, lifetime, mutability, and similar -issues, and no need to specify them in the contract. It also -prevents non-local interactions between the client and the -implementation, which makes them easier to understand and -maintain. Such objects can be used with generic -APIs that require pass-by-value, such as most containers.

+

Objects of copyable and movable types can be passed and returned by value, +which makes APIs simpler, safer, and more general. Unlike when passing objects +by pointer or reference, there's no risk of confusion over ownership, +lifetime, mutability, and similar issues, and no need to specify them in the +contract. It also prevents non-local interactions between the client and the +implementation, which makes them easier to understand, maintain, and optimize by +the compiler. Further, such objects can be used with generic APIs that +require pass-by-value, such as most containers, and they allow for additional +flexibility in e.g., type composition.

Copy/move constructors and assignment operators are usually easier to define correctly than alternatives @@ -1151,54 +1153,39 @@ in some cases.

-

Many types do not need to be copyable, and providing copy -operations for them can be confusing, nonsensical, or outright -incorrect. Copy/assigment operations for base class types are -hazardous, because use of them can lead to -object -slicing. Defaulted or carelessly-implemented copy operations -can be incorrect, and the resulting bugs can be confusing and -difficult to diagnose.

+

Some types do not need to be copyable, and providing copy +operations for such types can be confusing, nonsensical, or outright +incorrect. Types representing singleton objects (Registerer), +objects tied to a specific scope (Cleanup), or closely coupled to +object identity (Mutex) cannot be copied meaningfully. +Copy operations for base class types that are to be used +polymorphically are hazardous, because use of them can lead to +object slicing. +Defaulted or carelessly-implemented copy operations can be incorrect, and the +resulting bugs can be confusing and difficult to diagnose.

Copy constructors are invoked implicitly, which makes the -invocation easy to miss. This may cause confusion, particularly -for programmers used to languages where pass-by-reference is -conventional or mandatory. It may also encourage excessive -copying, which can cause performance problems.

- - +invocation easy to miss. This may cause confusion for programmers used to +languages where pass-by-reference is conventional or mandatory. It may also +encourage excessive copying, which can cause performance problems.

-

Make your type copyable/movable if it will be useful, and if it makes sense -in the context of the rest of the API. As a rule of thumb, if the behavior -(including computational complexity) of a copy isn't immediately obvious to -users of your type, your type shouldn't be copyable. If you define a copy or -move constructor, define the corresponding assignment operator, and vice-versa. -If your type is copyable, do not define move operations unless they are -significantly more efficient than the corresponding copy operations. If your +

Provide the copy and move operations if their meaning is clear to a casual +user and the copying/moving does not incur unexpected costs. If you define a +copy or move constructor, define the corresponding assignment operator, and +vice-versa. If your type is copyable, do not define move operations unless they +are significantly more efficient than the corresponding copy operations. If your type is not copyable, but the correctness of a move is obvious to users of the type, you may make the type move-only by defining both of the move operations.

If your type provides copy operations, it is recommended that you design -your class so that the default implementation of those operations is correct -and that you explicitly define them with = default. Remember to -review the correctness of any defaulted operations as you would any other -code.

- -
class Foo {  // Copyable and movable type.
- public:
-  Foo(Foo&& other) = default;
-  Foo(const Foo& other) = default;
-  Foo& operator=(Foo&& other) = default;
-  Foo& operator=(const Foo& other) = default;
-
- private:
-  string field_;
-};
-
+your class so that the default implementation of those operations is correct. +Remember to review the correctness of any defaulted operations as you would any +other code, and to document that your class is copyable and/or cheaply movable +if that's an API guarantee.

class Foo {
  public:
@@ -1218,93 +1205,11 @@ copyable, provide a public virtual Clone()
 method, and a protected copy constructor that derived classes
 can use to implement it.

-

If you do not want to support copy/move operations on -your type, explicitly disable them using = delete or -whatever -other mechanism your project uses. +

If you do not want to support copy/move operations on your type, +explicitly disable them using = delete in +the public: section.

-

- -

Delegating and Inheriting Constructors

- -
-

Use delegating and inheriting -constructors when they reduce code duplication.

-
- -
- -
- -

Delegating and inheriting constructors are two -different features, both introduced in C++11, for -reducing code duplication in constructors. Delegating -constructors allow one of a class's constructors to -forward work to one of the class's other constructors, -using a special variant of the initialization list -syntax. For example:

- -
X::X(const string& name) : name_(name) {
-  ...
-}
-
-X::X() : X("") {}
-
- -

Inheriting constructors allow a derived class to have -its base class's constructors available directly, just as -with any of the base class's other member functions, -instead of having to redeclare them. This is especially -useful if the base has multiple constructors. For -example:

- -
class Base {
- public:
-  Base();
-  Base(int n);
-  Base(const string& s);
-  ...
-};
-
-class Derived : public Base {
- public:
-  using Base::Base;  // Base's constructors are redeclared here.
-};
-
- -

This is especially useful when Derived's -constructors don't have to do anything more than calling -Base's constructors.

-
- -
-

Delegating and inheriting constructors reduce -verbosity and boilerplate, which can improve -readability.

- -

Delegating constructors are familiar to Java -programmers.

-
- -
-

It's possible to approximate the behavior of -delegating constructors by using a helper function.

- -

Inheriting constructors may be confusing if a derived -class introduces new member variables, since the base -class constructor doesn't know about them.

-
- -
-

Use delegating and inheriting constructors when they reduce -boilerplate and improve readability. -Be cautious about inheriting constructors when your derived class has -new member variables. Inheriting constructors may still be appropriate -in that case if you can use in-class member initialization -for the derived class's member variables.

-
-

Structs vs. Classes

@@ -1718,7 +1623,7 @@ be in the following order:

  • Constants (static const data members)
  • -
  • Constructors
  • +
  • Constructors and assignment operators
  • Destructor
  • @@ -2190,8 +2095,6 @@ do use shared ownership, prefer to use you need to be compatible with older versions of C++. Never use std::auto_ptr. Instead, use std::unique_ptr.

    - - @@ -2628,9 +2531,10 @@ them.

    explicit type conversion is necessary.