string_viewoperator+ vs. StrCat()absl::Statusstd::bindabsl::optional and std::unique_ptrabsl::StrFormat()make_unique and private Constructors.boolexplicit= delete)switch Statements Responsibly= deleteAbslHashValue and Youcontains()std::optional parametersif and switch statements with initializersinline Variablesstd::unique_ptr Must Be MovedAbslStringify()vector.at()auto for Variable DeclarationsOriginally posted as totw/109 on 2016-01-14
By Greg Miller (jgm@google.com)
This document will explain when const is meaningful in function declarations,
and when it is meaningless and best omitted. But first, let us briefly explain
what is meant by the terms declaration and definition.
Consider the following code:
void F(int); // 1: declaration of F(int)
void F(const int); // 2: re-declaration of F(int)
void F(int) { /* ... */ } // 3: definition of F(int)
void F(const int) { /* ... */ } // 4: error: re-definition of F(int)
The first two lines are function declarations. A function declaration tells
the compiler the function’s signature and return type. In the above example, the
function’s signature is F(int). The constness of the function’s parameter type
is ignored, so both declarations are equivalent (See “Overloadable
declarations”.)
Lines 3 and 4 from the above code are both function definitions. A function
definition is also a declaration, but a definition also contains the
function’s body. Therefore, line 3 is a definition for a function with the
signature F(int). Similarly, line 4 is also a definition for the same
function, F(int), which will result in an error at link time. Multiple
declarations are allowed, but only a single definition is permitted.
Even though the definitions on lines 3 and 4 declare and define the same
function, there is a difference within their function bodies due to the way they
are declared. From the definition on line 3, the type of the function-parameter
variable within the function will be int (i.e., non-const). On the other hand,
the definition on line 4 will produce a function-parameter variable within the
function whose type is const int.
const in Function DeclarationsNot all const qualifications in function declarations are ignored. To quote
from “Overloadable declarations” ([over.load]) in the C++ standard (emphasis
added):
consttype-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations
The following are examples where const is significant and not ignored:
void F(const int* x); // 1
void F(const int& x); // 2
void F(std::unique_ptr<const int> x); // 3
void F(int* x); // 4
In the above examples, the x parameter itself is never declared const. Each
of the above functions accepts a parameter named x of a different type, thus
forming a valid overload set. Line 1 declares a function that accepts a “pointer
to an int that is const”. Line 2 declares a function that accepts a
“reference to an int that is const”. And line 3 declares a function that
accepts a “unique_ptr to an int that is const”. All of these uses of const
are important and not ignored because they are part of the parameter type
specification and are not top-level const qualifications that affect the
parameter x itself.
Line 4 is interesting because it does not include the const keyword at all,
and may at first appear to be equivalent to the declaration on line 1 given the
reasons cited at the beginning of this document. The reason that this is not
true and that line 4 is a valid and distinct declaration is that only top-level,
or outermost, const qualifications of the parameter type specification are
ignored.
To complete this example, let us look at a few more examples where a const is
meaningless and ignored.
void F(const int x); // 1: declares F(int)
void F(int* const x); // 2: declares F(int*)
void F(const int* const x); // 3: declares F(const int*)
Though few of us will ever truly master all the delightful obscurities of C++,
it is important that we do our best to understand the rules of the game. This
will help us write code that is understood by other C++ programmers who are
following the same rules and playing the same game. For this reason, it is
important that we understand when const qualification is meaningful in a
function declaration and when it is ignored.
Although there is no official guidance from the Google C++ style guide, and there is no single generally accepted opinion, the following is one reasonable set of guidelines:
const on function parameters in declarations that
are not definitions (and be careful not to copy/paste a meaningless
const). It is meaningless and ignored by the compiler, it is visual noise,
and it could mislead readers.const on function parameters in definitions at your (or
your team’s) discretion. You might follow the same rationale as you would
for when to declare a function-local variable const.