I\'m playing around with overloading operators in c++14, and I tried to match two types of arguments: any-old-const-char*, and a-string-literal.
That is, I\'m trying
Why is
const char*
preferred overconst char (&)[N]
?
The reason for this is rather technical. Even though the decay of a string literal from const char[N]
to const char*
is a conversion, it falls into the "lvalue transformation" category and is therefore considered by [over.ics.rank]/3 to be as good as no conversion at all. Since "no conversion" is required for either overload, the non-template overload wins.
Why is
const char (&)[N]
preferred overconst char (&)[]
(non-template)?
It is not possible to bind a reference to array of unknown bound to a value of type array of known bound. Instead, a reference to array of unknown bound can only be bound to values that are themselves arrays of unknown bound.
Why is
const char (&&)[N]
unable to compile?
A string literal is an lvalue so I'm not sure why you would expect this to work.
Is there a "right way" to capture literal strings?
You can use a helper function template that captures its argument using a forwarding reference so as to not destroy any type information (const char*
versus const char[N]
) then dispatch on the type using template specialization. You'll probably also want to use SFINAE to make sure it is disabled if anything other than a const char*
or const char[N]
is passed in. To wit,
template
struct f_helper;
template <>
struct f_helper {
void do_it(const char*) {
puts("pointer");
}
};
template <>
struct f_helper {
template
void do_it(const char (&)[N]) {
printf("array of length %zd\n", N);
}
};
template >::value ||
std::is_same>::value>::type>
void f(T&& s) {
f_helper>::value>{}.do_it(s);
}
Coliru link: http://coliru.stacked-crooked.com/a/0e9681868d715e87