I am currently thinking about how to best constrain a generic type of a template to an std::sting
as well as string literals. Therefore I compare the deduced type with the desired type using std::is_same
. In case of an std::string
this works right away. For a string literal, meaning a char const array, it only works if I use std::decay
on the type and then compare the result to the type char const *
. If I directly compare the deduced type to what I think it should be, is_same
returns false, as is illustrated by the following example code.
template <class TYPE>
void function(TYPE&& parameter)
{
//this doesn't work as expected
std::cout << typeid(TYPE).name() << " : " << typeid(char const [5]).name() << std::endl;
std::cout << std::is_same<char const [5], TYPE>::value << std::endl;
//this works as expected
std::cout << typeid(std::decay_t<TYPE>).name() << " : " << typeid(char const *).name() << std::endl;
std::cout << std::is_same<char const *, std::decay_t<TYPE>>::value << std::endl;
}
int main(int argc, char** argv)
{
function("name");
return 0;
}
The output generated is the following:
char const [5] : char const [5]
0
char const * __ptr64 : char const * __ptr64
1
Now, what I am wondering is why is_same
returns false in the first case even though the types appear to be identical.
The only possible explanation that I could come up with is that within the function std::is_same
a transformation similar to std::decay
is applied to the type (for instance a function call). But then again this transformation would also occur to the other type, yielding the same result and thus resulting in equality.
String literals are not passed by value as char const [N]
, but by reference as char const (&)[N]
.
This works correctly for me:
std::cout << std::is_same<char const (&)[5], TYPE>::value << std::endl;
Note here that
1) Refers to a
std::type_info
object representing the type type. If type is a reference type, the result refers to astd::type_info
object representing the referenced type.
You can easily verify that is_same
doesn't discard reference-ness in the same way as type_info
, for example by checking that
std::is_same<int&, int>::value == false
This explains why the typeid
name is the same, but your is_same
test still fails.