In C++ if I have a generic function:
template <typename T>
void func(T& s)
{
std::cout << "in generic\n";
std::cout << typeid(s).name();
}
T
will get deduced to typeid(s).name()
.
But how come if I do:
func("test");
That generic function works, but this one doesn't:
void func(const char*& s)
{
std::cout << "in overloaded\n";
std::cout << typeid(s).name();
}
I know that it'll work if I change const char*&
to const char*
or const char* const&
in the overloaded function's signature, and that if I want to pass an argument to the overloaded function it must be non-temporary. I just don't understand what happened to T&
, isn't it supposed to turn into const char*&
after the deduction?
String literals are arrays of const characters. So in the case of the template function called like this:
func("test");
T
is deduced as char const[5]
. And s
is a reference to the string literal, and its type is char const (&)[5]
. That is, a reference to an array of 5 const char.
The type of "test"
is const char[5]
. When calling a function template and using an argument to deduce a parameter of reference type, the array-to-pointer conversion does not happen. So the generic function deduces T
to be const char[5]
- you can see that the output for "test"
and for a const char*
differs:
template<typename T>
void func(T& s){
std::cout << "in generic\n";
std::cout << typeid(s).name() << '\n';
}
int main()
{
func("test");
const char *c = "test";
func(c);
}
GCC output:
in generic
A5_c
in generic
PKc
On the other hand, in the non-generic function, you want a reference to a non-const pointer to const char
. However, as the type of "test"
is const char[5]
, it has to undergo the array-to-pointer conversion, which means that the resulting const char*
is a temporary (an rvalue). As such, it cannot bind to a reference to non-const.
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