I have two functions :
void foo(const char * p)
and
template<size_t T_Size>
void foo(const char (& p)[T_Size]) ;
Given the call:
int main(int argc, char* argv[])
{
char a[21] ; // typeid : A21_c
sprintf(a, "a[21] : Hello World") ;
const char * b = "b : Hello World" ; // typeid : PKc
// note that literal "liter. : Hello World" has a typeid : A21_c
foo(a) ; // calls foo(const char (& p)[T_Size])
foo(b) ; // calls foo(const char * p)
foo("liter. : Hello World") ; // calls foo(const char * p) ???
return 0 ;
}
Apparently, calling foo
with a stack-based correctly declared array behaves as expected, while calling foo
with a literal "liter. : Hello World" does not, despite the two having the same type (according to RTTI).
What are exactly the rules followed by the symbol lookup to choose one overload over the other ?
Why the different behaviour between a declared array and a string literal ?
Thanks !
Note that a way to have the desired result (i.e. have a litteral string match the foo(const char (& p)[T_Size])
function) is to remove the void foo(const char *p)
and add instead:
struct FooIndirect
{
const char * m_p ;
FooIndirect(const char *p) : m_p(p) {}
} ;
void foo(const FooIndirect & p)
{
// do something with p.m_p
}
This indirection makes the templated foo a better match for string litterals, and still enables the user to use pointers (the indirection will be removed in optimized compilation mode).
I tested it on my g++ 4.4.3, but I believe it will work the same way on every compiler.
Table 9 in Chapter 13(Overload Resolution) of the Standards, ranks "Array to pointer" conversion (for non-template) to be of the same rank (EXACT MATCH) as "no Conversion Required" (for the template version).
Everything else being the same, the non-template version is preferred over the template version.