So, I'm aware that a string literal has a type of const char[N]
. And I'm also aware that if we got a const char[]
parameter in some function, compiler automatically converts it to const char*
.
But why do I always get compiler error messages saying that a string literal has a type of const char*
?
Here's a few examples:
void f(int x) {}
int main()
{
f("Hello");
return 0;
}
ERROR: invalid conversion from 'const char*' to 'int'
void f() {
throw "Hello";
}
int main()
{
try{ f(); } catch (int x) { std::cout << "No\n";}
return 0;
}
In terminal: terminate called after throwing an instance of 'char const*'
EDIT: I'm using GNU GCC.
Why does const char[] get converted to const char* all the time?
Generally, because there is another rule closely related to the function parameter adjustment that you mentioned:
[conv.array] Array-to-pointer conversion
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion ([conv.rval]) is applied. The result is a pointer to the first element of the array.
[basic.lval] Value category
Whenever a glvalue appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue, array-to-pointer, or function-to-pointer standard conversions are applied to convert the expression to a prvalue.
Colloquially, this implicit conversion is called pointer decaying.
The error message appears to describe an attempt to convert this intermediary result of lvalue-to-rvalue conversion to the parameter type.
In terminal: terminate called after throwing an instance of 'char const*'
In this particular case of exception throwing, there is a specific rule, which is essentially same as pointer decaying, but in context of a throw:
[expr.throw] Throwing an exception
Evaluating a throw-expression with an operand throws an exception; the type of the exception object is determined by removing any top-level cv-qualifiers from the static type of the operand and adjusting the type from “array of T” or function type T to “pointer to T”.
So, the adjusted type of the exception object is in fact const char*
, and it is this uncaught object that the compiler generated message describes.
For completeness, here is the parameter adjustment rule that you knew:
[dcl.fct] Functions
... After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T”
P.S. there is also an analogous adjustment rule for exception handlers:
[except.handle] Handling an exception
A handler of type “array of T” or function type T is adjusted to be of type “pointer to T”.