I don\'t understand why the array decays to a pointer in a template function.
If you look at the following code: When the parameter is forced to be a reference (fun
To quote from spec, it says
(14.8.2.1/2) If P is not a reference type: — If A is an array type, the pointer type produced by the array-to-pointer standard conversion (4.2) is used in place of A for type deduction; otherwise
So, in your case, It is clear that,
template <class T>
void f1(T& buff) {
std::cout << "f:buff size:" << sizeof(buff) << std::endl; //prints 3
}
doesn't decay into pointer.
The reason basically boils down to type deduction when matching the different overloads. When you call f
the compiler deduces the type to be const char[3]
which then decays into const char*
because that's what arrays do. This is done in the same exact way that in f(1)
the compiler deduces T to be int
and not int&
.
In the case of f1
because the argument is taken by reference, then the compiler again deduces T to be const char[3]
, but it takes a reference to it.
Nothing really surprising, but rather consistent if it were not for the decay of arrays to pointers when used as function arguments...
Because functions can't have arrays as arguments. They can have array references though.
Because arrays can not be passed by value as a function parameter.
When you pass them by value they decay into a pointer.
In this function:
template <class T>
void f(T buff) {
T can not be char (&buff)[3]
as this is a reference. The compiler would have tried char (buff)[3]
to pass by value but that is not allowed. So to make it work arrays decay to pointers.
Your second function works because here the array is passed by reference:
template <class T>
void f1(T& buff) {
// Here T& => char (&buff)[3]
It is because arrays cannot be passed by value to a function. So in order to make it work, the array decays into a pointer which then gets passed to the function by value.
In other words, passing an array by value is akin to initializing an array with another array, but in C++ an array cannot be initialized with another array:
char buff[3] = {0,0,0};
char x[3] = buff; //error
So if an array appears on the right hand side of =
, the left hand side has to be either pointer
or reference
type:
char *y = buff; //ok - pointer
char (&z)[3] = buff; //ok - reference
Demo : http://www.ideone.com/BlfSv
It is exactly for the same reason auto
is inferred differently in each case below (note that auto
comes with C++11):
auto a = buff; //a is a pointer - a is same as y (above)
std::cout << sizeof(a) << std::endl; //sizeof(a) == sizeof(char*)
auto & b = buff; //b is a reference to the array - b is same as z (above)
std::cout << sizeof(b) << std::endl; //sizeof(b) == sizeof(char[3])
Output:
4 //size of the pointer
3 //size of the array of 3 chars
Demo : http://www.ideone.com/aXcF5