I am reading Effective modern C++ from Scott Meyers. Item 1 contains the following example:
template<typename T>
void f(T& param); // param is a reference
int x = 27; // x is an int
const int cx = x; // cx is a const int
f(cx); // T is const int,
// param's type is const int&
In Item 3 appears the following example:
Widget w;
const Widget& cw = w;
auto myWidget1 = cw; // auto type deduction:
// myWidget1's type is Widget
Based on Item 1 I expected myWidget1
's type to be const Widget
. Am I missing something?
In most cases auto
follows the rules of template argument deduction:
§ 7.1.6.4 [dcl.spec.auto]/p6:
Once the type of a declarator-id has been determined according to 8.3, the type of the declared variable
using the declarator-id is determined from the type of its initializer using the rules for template argument
deduction. Let T
be the type that has been determined for a variable identifier d
. Obtain P
from T
by
replacing the occurrences of auto
with either a new invented type template parameter U
or, if the initializer
is a braced-init-list (8.5.4), with std::initializer_list<U>
. The type deduced for the variable d
is then the deduced A
determined using the rules of template argument deduction from a function call (14.8.2.1).
§ 14.8.2.1 [temp.deduct.call]/p2:
If P
is not a reference type:
If you want myWidget1
to be of type const Widget&
, it should be declared as a reference type, e.g.:
auto& myWidget1 = cw;
// ^
DEMO
auto myWidget1 = cw;
follows the third rule of template argument type deduction in Meyers book, which is pass by value.
When you pass by value, cv-qualifiers and references are ignored, because you are getting a new copy of the object, so you don't really care if the old object that you copied from was const or a reference.