Why does const have to be added to constexpr for a string literal declaration?

Doesn't constexpr imply const?

It does, on the object being declared, in your case s. The result of applying constexpr is the object

char *const s;

It's still declared to point at a non-const object. Only the address has to be a constant expression. Which means it must be to an object with static storage duration.

Is it possible for something to be constexpr but change in some other way such that is not constant?

No. But then again, it's not the object being declared constexpr that is allowed to change here. For instance

static char foo[] = "abc"; // Not a constant array
constexpr  char * s  = foo; // But the address is still a valid initializer.

Is a valid pair of declarations.


const applies to the thing on its left, or if nothing is there then to its right.

In char *const s = "hello";, the const is applied to the *, not to the char, so s is a const pointer to non-const char data. However, a string literal is const char data (in this case, "hello" is a const char[6]). You can't have a pointer to non-const data that is actually pointing at const data, that would allow the const data to be modifiable, which is undefined behavior if something actually tried to modify the data. That is what the compiler error is complaining about.

So, you need a pointer to const char data instead:

char const *const s = "hello";

Or:

const char *const s = "hello";

The constexpr just makes the s variable available for evaluation at compile-time.