#include <iostream>
using namespace std;
void f(const char* arg)
{
cout << "arg is a pointer" << endl;
}
template<size_t N>
void f(const char (&arg)[N])
{
cout << "arg is an array." << endl;
}
int main()
{
f("");
}
My compiler is clang 3.8.
The output is:
arg is a pointer
However, according to cppreference.com,
The type of an unprefixed string literal is const char[].
Why does the overload resolution not behave as expected?
It does behave as expected, you just need to adjust your expectations ;-)
const char[1]
and const char (&)[1]
are different types.
The conversions to const char*
(array-to-pointer conversion) and const (&char)[1]
(identity conversion) are both considered exact matches, but a non-template is a better match than a template.
If you write a non-template size-specific overload,
void f(const char (&arg)[1])
you will get an error that the function call is ambiguous.
@molbdnilo's answer is correct. To add one detail: Your intuition would be correct and the compiler would prefer to avoid the array-to-pointer conversion by calling the template. But lvalue transformations (lvalue-to-rvalue, array-to-pointer, and function-to-pointer) are specifically ignored in overload ranking, according to [over.ics.rank] §13.3.3.2/3.2.1.
There is a workaround: add a fake volatile
to restore the balance of overload preference. Just be sure to remove it by const_cast
before using the parameter.
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