Can any one help me understand the following code
#include <iostream> void foo(const char * c) { std::cout << "const char *" << std::endl; } template <size_t N> void foo(const char (&t) [N]) { std::cout << "array ref" << std::endl; std::cout << sizeof(t) << std::endl; } int main() { const char t[34] = {'1'}; foo(t); char d[34] = {'1'}; foo(d); }
The output is
const char * array ref 34
Why does the first foo calls the const char *
version ? How can I make it call the reference version ?
Passing arrays to functions in C/C++ are passed by reference. Even though we do not create a reference variable, the compiler passes the pointer to the array, making the original array available for the called function's use. Thus, if the function modifies the array, it will be reflected back to the original array.
To pass an entire array to a function, only the name of the array is passed as an argument. result = calculateSum(num); However, notice the use of [] in the function definition. This informs the compiler that you are passing a one-dimensional array to the function.
The only reason for passing an array explicitly by reference is so that you can change the pointer to point to a different array. If a function only looks at the contents of an array, and does not change what is in the array, you usually indicates that by adding const to the parameter.
Arrays are used to store multiple values in a single variable, instead of declaring separate variables for each value. To create an array, define the data type (like int ) and specify the name of the array followed by square brackets [].
Conversion of const char[N]
to const char*
is considered an "exact match" (to make literals easier, mainly), and between two exact matches a non-template function takes precedence.
You can use enable_if
and is_array
to force it to do what you want.
A messy way to force it might be:
#include <iostream> template <typename T> void foo(const T* c) { std::cout << "const T*" << std::endl; } template <typename T, size_t N> void foo(const T (&t) [N]) { std::cout << "array ref" << std::endl; } int main() { const char t[34] = {'1'}; foo(t); char d[34] = {'1'}; foo(d); } /* array ref array ref */
I realise that the OP had char
not some generic T
, but nonetheless this demonstrates that the problem lay in one overload being a template and not the other.
Let's look at this modified example with no template.
void foo(const char * c) { std::cout << "const char *" << std::endl; } void foo(const char (&t) [34]) { std::cout << "const char (&) [34]" << std::endl; } int main() { const char t[34] = {'1'}; foo(t); }
My compiler says call of overloaded foo
is ambiguous. This is because conversions from array to pointer are considered an "Exact" conversion sequence and are not better than the null conversion sequence for overload resolution (Standard section 13.3.3.1.1.)
In the original code, the template parameter N
can be deduced as 34, but then both non-template foo(const char*)
and foo<34>(const char (&)[34])
are considered in overload resolution. Since neither is better than the other by conversion rules, the non-template function beats the template function.
Fixing things seems tricky. It seems like the is_array
template from header <type_traits>
(from C++0x if possible or Boost if not) might help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With