const int ci = 10;
auto i = ci; // i will be \"int\" instead of \"const int\"
i = 20;
I am wondering why auto is designed for this kind of behavio
auto
by itself means that you want a new, locally-owned variable with a copy of the given value. const
-ness is not part of value. An int
is an int
whether it's specified using a literal, a named constant, an expression, or a non-const
variable.
auto i = 3,
j = i,
k = ci,
m = 3 + 4; // All these variables are type int.
To get a constant of deduced type, you can still use auto const
. This expresses within the declaration how the variable may be used.
const auto i = 3;
Since C++14, there is also the decltype(auto)
specifier which applies decltype
to the initializer, to make a carbon copy of the given variable. Perhaps that's really what you expected:
decltype(auto) i = ci; // i receives type const int.
Live demo.
decltype(auto)
is a bit tricky, though, and it has few use cases aside from its original purpose relating to deciding the return type of function call wrappers. Unless there's a good reason, choose const auto
or const int
instead.
Another alternative is to use a forwarding reference, spelled auto &&
. This refers to the variable or value that initializes it, whatever that may be.
auto && i = ci; // i receives type const int & and aliases ci.
This is less expressive and specific, but reliably declares i
as an alias to ci
. The other thing you tried was auto &
, which is similar but only allows forming a reference to a preexisting variable.
auto & i = ci; // i receives type const int & and aliases ci.
A reference to a const int
variable must be of type const int &
, because otherwise it would permit illegal modification.
auto
mostly follows the same type deduction rules as template argument deduction. The only difference is that auto
will deduce std::initializer_list
from a braced-init-list in some cases, while template argument deduction doesn't do this.
From N3337, §7.1.6.4 [dcl.spec.auto]
6 ... The type deduced for the variable
d
is then the deducedA
determined using the rules of template argument deduction from a function call (14.8.2.1), ...
The behavior you're observing is the same as what template argument deduction would do when deducing types from a function call
§14.8.2.1 [temp.deduct.call]
2 If
P
is not a reference type:
— ...
— IfA
is a cv-qualified type, the top level cv-qualifiers ofA
’s type are ignored for type deduction.
Thus, in
auto i = ci;
the top level const
qualifier is ignored and i
is deduced as int
.
When you write
auto& i = ci;
then i
is no longer not a reference type and the above rule doesn't apply, so the const
qualifier is retained.