What are the type deduction rules for auto*
?
Consider the following:
int x = 64;
int* px = &x;
auto* v1 = &x; // auto => ??? ok v1 is int* ...
auto* v2 = px; // auto => ??? is v2 int* ?
auto* v3 = &px; // auto => ??? is v3 int** ?
Just to clarify my question if we split the type deduction into two steps:
auto
" itself without (*
) ... thenv1
, v2
and v3
) after adding the (*
)So my two questions are:
auto
be deduced to without the (*
) ?v2
be pointer to int
(int*
) and v3
pointer to pointer (int**
) ?If you know template type deduction you will know almost all there is to auto
type deduction. Because auto type deduction works like template type deduction.
When a variable is declared using auto
, then auto
acts as T
in a template, and the type specifier acts as the parameter type:
const auto i = 20;
Would translate to:
template<typename T>
void func(const T param) { ... }
// ^^^^^^^
And with reference:
const auto& j = i;
Translates to:
template<typename T>
void func(const T& param)
// ^^^^^^^^
With pointers, it's the same:
auto* v1 = &x;
Becomes
template<typename T>
void func(T* param)
Since x
is an int
, then auto* == int*
.
And auto* v2 = px;
is also int*
Now, the third one you have:
auto* v3 = &px;
Becomes int**
since you're taking the address of the pointer.
template<typename T>
void func(T** param)
// ^^^
A handy way to see the type of auto is to use what others have mentioned, the typeid()
function.
But I like to use <boost/type_index.hpp>
to show the type correctly:
#include <iostream>
#include <boost/type_index.hpp>
using namespace std;
using namespace boost::typeindex;
int main()
{
int x = 64;
int* px = &x;
auto* v1 = &x;
auto* v2 = px;
auto* v3 = &px;
cout << type_id_with_cvr<decltype(v1)>().pretty_name() << '\n';
cout << type_id_with_cvr<decltype(v2)>().pretty_name() << '\n';
cout << type_id_with_cvr<decltype(v3)>().pretty_name() << '\n';
}
Which outputs:
int*
int*
int**
There is one important difference between auto type deduction and template type deduction, namely std::initializer_list<>
Consider these examples:
auto i = 1; // int
auto j(1); // int
auto k = { 1 }// std::initializer_list<int> !
auto l { 1 } // std::initializer_list<int> !
As you see, using brace initializer with auto can be trouble.
You can however manually write the type before the braces to ensure that the type is correct but I don't see the point in that:
auto i = int{ 1 }; // type is int
There are new auto rules that have been implemented already in Clang 3.8 that makes it possible to use direct-list-initialization with auto (upcoming standard)