Let's say we have
template <const char*>
struct A{};
// static storage
const char a[] = "asd";
const char* p = "asd";
This instantiation
A<a>{};
is okay for compiler. And this is understandable - array a
decays to pointer to first element. But if we instantiate A
with p
like this
A<p>{};
compiler gives an error:
error: non-type template argument of type 'char *' is not a constant expression
Why doesn't Standard allow to specify named variable of type const char*
or just string literal "asd"
, which is btw lvalue itself, as a template argument?
The array a
is a constant array of character, it's fully initialized at the time of compilation and also gets a know memory address by the compiler which is why it can decay to a pointer in a template.
But p
is a pointer to a constant array of characters, but the pointer itself is not a compile-time constant, and can be changed to point to other strings, and it's is not initialized at time of compilation but either on time of linking (which happens after compilation) or when the program is loaded into memory. The address of p
is known at time of compilation, but not the address of the string literal p
points to.
To expand on the reason the address of the string literal is not known at time of compilation, it's because it's put in a special read-only segment by the compilers code-generator, and that read-only segment is then combined with the read-only segments from the other translation units when linking. This is why the final address of the string literal can't be known until the time of linking (at earliest).
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