diff --git a/cppguide.html b/cppguide.html index 7c6db3c..c5c7b98 100644 --- a/cppguide.html +++ b/cppguide.html @@ -346,8 +346,21 @@ void test(D* x) { f(x); } // Calls f(B*)
-Try to avoid forward declarations of entities -defined in another project.
+Do not use forward declarations of entities that your project + does not own.
+ +For entities that you do own: +
Implementation inheritance reduces code size by re-using +
Implementation inheritance reduces code size by reusing the base class code as it specializes an existing type. Because inheritance is a compile-time declaration, you and the compiler can understand the operation and detect @@ -1880,7 +1893,9 @@ In some cases reference parameters can bind to temporaries, leading to lifetime bugs. Instead, find a way to eliminate the lifetime requirement (for example, by copying the parameter), or pass retained parameters by pointer and document the lifetime and non-null requirements. -See TotW 116 for more.
+See TotW 116 for more. + +When ordering function parameters, put all input-only parameters before any output parameters. In particular, @@ -2091,6 +2106,33 @@ C++ that may differ from what you see elsewhere.
+Use cpplint.py to detect style errors.
cpplint.py
+is a tool that reads a source file and identifies many
+style errors. It is not perfect, and has both false
+positives and false negatives, but it is still a valuable
+tool.
Some projects have instructions on
+how to run cpplint.py from their project
+tools. If the project you are contributing to does not,
+you can download
+
+cpplint.py separately.
Prefer to have single, fixed owners for dynamically @@ -2218,31 +2260,6 @@ do use shared ownership, prefer to use
Never use std::auto_ptr. Instead, use
std::unique_ptr.
Use cpplint.py to detect style errors.
cpplint.py
-is a tool that reads a source file and identifies many
-style errors. It is not perfect, and has both false
-positives and false negatives, but it is still a valuable
-tool.
Some projects have instructions on
-how to run cpplint.py from their project
-tools. If the project you are contributing to does not,
-you can download
-
-cpplint.py separately.
Use rvalue references only in certain special cases listed below.
@@ -2292,7 +2309,7 @@ rules apply. Such a reference is called a forwarding reference.dynamic_cast may be used freely on the
-object. Usually one
-can use a static_cast as an alternative in
-such situations.
+object. Usually
-Decision trees based on type are a strong indication
+
+absl::down_cast provides an even better
+alternative.
+
+
Decision trees based on type are a strong indication that your code is on the wrong track.
if (typeid(*data) == typeid(D1)) {
@@ -2676,7 +2695,12 @@ them.
In general, do not use C-style casts. Instead, use these C++-style
casts when explicit type conversion is necessary.
-
+Some are part of the standard C++ language,
+and some are defined in
+
+
+ absl/base/casts.h. Use the first that
+correctly applies:
absl::down_cast
+ to cast a pointer from a superclass
+ to a subclass. You must be sure your object is actually
+ an instance of the subclass.const_cast to remove the
const qualifier (see const).int16_t, uint32_t,
int64_t, etc. You should always use
those in preference to short, unsigned
long long, and the like, when you need a guarantee
-on the size of an integer. Prefer to omit the std::
-prefix for these types, as the extra 5 characters do
-not merit the added clutter. Of the built-in integer types, only
+on the size of an integer. Of the built-in integer types, only
int should be used. When appropriate, you
are welcome to use standard type aliases like
size_t and ptrdiff_t.
@@ -3061,6 +3086,9 @@ assertions for this.
+Prefer to omit the std:: prefix on standard library
+integer types, as the extra 5 characters do not merit the added clutter.
If your code is a container that returns a size, be sure to use a type that will accommodate any possible usage of your container. When in doubt, use a larger type @@ -3282,6 +3310,10 @@ be deduced by the compiler, rather than spelled out explicitly in the code:
void f(T t); f(0); // Invokes f<int>(0) + A lambda expression can also have template parameters, which are deduced in the same way: +// Sort `vec` in decreasing order
+std::sort(vec.begin(), vec.end(), []<typename T>(T lhs, T rhs) { return lhs > rhs; });
+
auto variable declarationsauto keyword in place
@@ -3316,11 +3348,10 @@ auto d{42}; // d is an int, not a std::initializer_list<int>
rely on type deduction; it's just an alternative syntax for an explicit
return type.
auto keyword in place of
- 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 each auto function parameter:
+ auto parametersauto keyword in place of
+ one or more of its parameter types. This causes it to be a function template instead of an
+ ordinary function, with a separate template parameter for each auto function parameter:
// Sort `vec` in decreasing order
std::sort(vec.begin(), vec.end(), [](auto lhs, auto rhs) { return lhs > rhs; });
Explicit types for elements of map-like containers are easy to
+ get wrong. In those cases structured
+ bindings for the key and value are almost always clearer than a single
+ variable representing the pair.
Do not use decltype(auto) if a simpler option will work;
because it's a fairly obscure feature, it has a high cost in code
clarity.
See TotW #232 for more details on
+ when to use auto for variable declarations.
Use return type deduction (for both functions and lambdas) only if the @@ -3462,16 +3501,30 @@ std::array numbers = {4, 8, 15, 16, 23, 42}; is the interface. In particular, public functions in header files should almost never have deduced return types.
-auto parameter types for lambdas should be used with caution,
- because the actual type is determined by the code that calls the lambda,
- rather than by the definition of the lambda. Consequently, an explicit
- 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.,
- the std::sort example above).
Avoid using parameter type deduction (using either auto or template
+ parameters) if you can give the parameter a specific type instead. If it will only
+ be called with one type, it will almost always be clearer to make that type explicit,
+ unless it is called very close to where it's defined (so that the reader can easily
+ see both), or it's a lambda being passed to an interface so well-known that it's
+ obvious what type it will eventually be called with (e.g., the std::sort
+ example above)
Do not use auto parameters in non-lambda functions. Use named template parameters
+ instead, because they are more explicit about the fact that the function is a template:
void F(auto arg) { ... }
+
+template <typename T>
+void F(T arg) { ... }
+
+
+In a lambda expression, if you need to refer to the type of a parameter, prefer to make that + type a template parameter:
+[](auto x) { decltype(x) y; ... }
+
+ []<typename T>(T x) { T y; ... }
+
insert
forces you to.
+The elements of containers like std::map<K, V> benefit
+ especially from structured bindings; not only can the two parts of the pair be
+ given more specific names, but the use of type deduction dodges the common bug
+ of failing to const-qualify the key type of the element, which
+ often surprisingly succeeds in compiling by introducing unintended
+ copying.
If the object being bound is a struct, it may sometimes be helpful to provide names that are more specific to your usage, but keep in mind that this may also mean the names are less recognizable to your reader than the @@ -4016,115 +4076,12 @@ documentation.
project-wide use by your project leads. Do not roll your own promise or awaitable types. -Use only approved libraries from the Boost library -collection.
- - -The - -Boost library collection is a popular collection of -peer-reviewed, free, open-source C++ libraries.
- - -Boost code is generally very high-quality, is widely -portable, and fills many important gaps in the C++ -standard library, such as type traits and better binders.
- - -Some Boost libraries encourage coding practices which can -hamper readability, such as metaprogramming and other -advanced template techniques, and an excessively -"functional" style of programming.
- - - - - -In order to maintain a high level of readability for -all contributors who might read and maintain code, we -only allow an approved subset of Boost features. -Currently, the following libraries are permitted:
- -boost/call_traits.hppboost/compressed_pair.hppboost/graph,
- except serialization (adj_list_serialize.hpp) and
- parallel/distributed algorithms and data structures
- (boost/graph/parallel/* and
- boost/graph/distributed/*).boost/property_map, except
- parallel/distributed property maps (boost/property_map/parallel/*).boost/iteratorboost/polygon/voronoi_builder.hpp,
- boost/polygon/voronoi_diagram.hpp, and
- boost/polygon/voronoi_geometry_type.hppboost/bimapboost/math/distributionsboost/math/special_functionsboost/math/toolsboost/multi_indexboost/heapboost/container/flat_map, and
- boost/container/flat_setboost/intrusive.boost/sort library.boost/preprocessor.We are actively considering adding other Boost -features to the list, so this list may be expanded in -the future.
-As with Boost, some modern C++ -library functionality encourages coding practices that hamper +
Some modern C++ library functionality encourages coding practices that hamper readability — for example by removing checked redundancy (such as type names) that may be helpful to readers, or by encouraging template @@ -4155,6 +4112,51 @@ and conversion costs.
+When choosing to use third-party libraries, be consistent with the code + around you.
+ + +A third-party library is a library that is not primarily developed in the + same repository as your code.
+ + +When choosing a library to solve a particular problem, first check if there's + already a library that your codebase typically uses for that kind of problem. + If so, use it. If not, prefer libraries from the following sources, in roughly + decreasing order of priority:
+ +If you choose to use a third-party library, make sure to follow + + your codebase's policies for third-party code.
+Nonstandard extensions to C++ may not be used unless otherwise specified.
@@ -4546,7 +4548,7 @@ class members, which should follow the rules for private: std::string table_name_; // OK - underscore at end. - static Pool<TableInfo>* pool_; // OK. + static Pool<TableInfo>* absl_nullable pool_; // OK. }; @@ -4559,7 +4561,7 @@ the trailing underscores that data members in classes have.struct UrlTableProperties {
std::string name;
int num_entries;
- static Pool<UrlTableProperties>* pool;
+ static Pool<UrlTableProperties>* absl_nullable pool;
};
@@ -4846,8 +4848,10 @@ declaration:
call. This is quite common for pointer/reference arguments to
constructors.
- It is allowed (if unusual) to declare multiple variables in the same declaration, but it is disallowed if any of those have pointer or reference decorations. Such declarations are easily misread.
@@ -5792,11 +5798,12 @@ needed) is: public: // Note the 1 space indent! MyClass(); // Regular 2 space indent. explicit MyClass(int var); + MyClass(const MyClass& other); + MyClass& operator=(const MyClass& other); ~MyClass() {} void SomeFunction(); - void SomeFunctionThatDoesNothing() { - } + void SomeFunctionThatDoesNothing() {} void set_some_var(int var) { some_var_ = var; } int some_var() const { return some_var_; }