string_view
operator+
vs. StrCat()
absl::Status
std::bind
absl::optional
and std::unique_ptr
absl::StrFormat()
make_unique
and private
Constructors.bool
explicit
= delete
)switch
Statements Responsibly= delete
AbslHashValue
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 ([email protected])
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):
const
type-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
.