问题
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:
- Deducing the type of "
auto" itself without (*) ... then - Deducing the type of the object (
v1,v2andv3) after adding the (*)
So my two questions are:
- What will
autobe deduced to without the (*) ? - Will
v2be pointer toint(int*) andv3pointer to pointer (int**) ?
回答1:
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)
回答2:
auto will deduce to cv-qualified type of the expression given. auto* will deduce to the cv-qualified type of the type expression points to - if expression is a pointer - and will fail to compile otherwise.
For given examples, actual type of v would be pointer to int, same with v2, and for v3 it would be pointer to pointer to int.
If your first example would be written as auto v1 = &px, type of v1 would remain the same.
回答3:
You can use typeid to answer your question.
#include <iostream>
#include <typeinfo>
using namespace std;
int main() {
// your code goes here
int x = 64;
int* px = &x;
auto* v1 = &x;
auto* v2 = px;
auto* v3 = &px;
cout<<typeid(v1).name()<<endl;
cout<<typeid(v2).name()<<endl;
cout<<typeid(v3).name()<<endl;
return 0;
}
Output:
Pi
Pi
PPi
Pi --> pointer to integer variable
PPi --> pointer to a pointer to integer variable
回答4:
The deduction process is the same as a template parameter. If I do:
int a = 0;
auto* b = &a;
The type of b will be int*. And writing:
auto b = &a;
Will result in the same type, int*.
In your example, the compiler will in some sort add the missing star. But the simplest form would be to just write auto
来源:https://stackoverflow.com/questions/36652180/what-are-the-type-deduction-rules-for-auto