I'm learning how to use template in C++11 and I just read an article about template, it showed me the rules of type deduction with reference. For example,
template<typename T>
void f(const T& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // T is int, param's type is const int&
f(cx); // T is int, param's type is const int&
f(rx); // T is int, param's type is const int&
f(27); // T is int, param's type is const int&
Besides, it also talked about the reference collapsing:
template<typename T>
void f(T&& param);
int x = 27;
const int cx = x;
const int& rx = x;
f(x); // x is lvalue, so T is int&, param's type is int&
f(cx); // cx is lvalue, so T is const int&, param's type is const int&
f(rx); // rx is lvalue, so T is const int&, param's type is const int&
f(27); // 27 is rvalue, so T is int, param's type is int&&
Well, for now I understood all of these but now, I'm thinking about pointer. This issue totally explode my brain but it seems that it would become extremely complex.
For example, let's say we have int *
, const int *
. Now if we have threse template functions below:
template<typename T>
void f(T param);
template<typename T>
void f(T *param);
template<typename T>
void f(const T *param);
template<typename T>
void f(T& param);
template<typename T>
void f(const T& param);
template<typename T>
void f(T&& param);
If we pass a int *
, how does the compile do the type deduction? What about a const int *
?
As you know, type deduction in templates falls in three different categories, wherein parameter type of the template function is either a 1) reference or pointer, 2) a forwarding (a.k.a universal) reference, or finally 3) neither pointer/reference or forwarding reference.
So, if you have a pointer, type deduction is working like this is these three cases.
For case 1-A:
template<typename T>
void f(T* param);
int x = 27;
int* px = &x;
const int* cpx = &x;
f(px); // T is int and param's type is int *
f(cpx); // T is const int and param's type is const int *
For case 1-B:
template<typename T>
void f(T& param);
int x = 27;
int* px = &x;
const int* cpx = &x;
f(px); // T is int* and param's type is int*&
f(cpx); // T is const int* and param's type is const int*&
For case 2:
template<typename T>
void f(T&& param);
int x = 27;
int* px = &x;
const int* cpx = &x;
f(px); // T is int*& and param's type is int*&
f(cpx); // T is const int*& and param's type is const int*&
For case 3:
template<typename T>
void f(T param);
int x = 27;
int* px = &x;
const int* cpx = &x;
f(px); // T is int * and param's type is int *
f(cpx); // T is const int * and param's type is const int *