I have a small question about type deduction in C++ metaprogramming. There is a certain function do some action.
main.cpp
template<typename T> void foo(T arg) {
// do some action on argument
std::cout << typeid(arg).name() << std::endl;
}
int main(int argc, char** argv) {
int array[100] = {0};
std::cout << typeid(array).name() << std::endl;
foo(array);
return 0;
}
Output:
A100_i
Pi
Why arg in function foo() have a another data type than array in function main()?
Because C style arrays are broken. In particular, you cannot have a function argument with a C style array type; if you write a function (forgetting about templates for the moment):
void foo( int arg[100] );
the language requires the compiler to treat this as:
void foo( int* arg );
(and the 100
is just a comment—it is ignored by the
compiler).
In order to support this in the case of templates, if the compiler is trying to match a non-reference template argument, it will convert an array argument to a pointer, and type deduction will result in the pointer type, not the array type.
The result is that you should never write a function (template
or otherwise) expecting a C style array (except for the second
argument of main
, where you don't have a choice).
Since this brokeness is only present for reasons of C compatibility, C++ doesn't follow it when references are involved. So:
template < typename T, size_t N >
void foo( T (&arg)[ N ] );
will work, and should give you the same results in both cases. If you think that your function might be called with both C style arrays and other things (e.g. std::vector), you can overload it for both. The version above is more specialized, and will be preferred to the more generic version if possible.
A better solution would be to avoid C style arrays entirely, but
they are useful for static variables with initialization; it's
only with C style arrays that you can get the compiler to count
the number of elements, and define the size of the array
according to the initializer list. And have static
initialization; std::vector
will count the initializers at
runtime, but used as a static variable, may cause order of
initialization problems.
C style arrays and