In a discussion on another question, I was given an example where apparently linkage of an identifier affected its usability in a constant expression:
extern char const a[] = "Alpha";
char constexpr b[] = "Beta";
char const g[] = "Gamma";
template <const char *> void foo() {}
auto main()
-> int
{
foo<a>(); // Compiles
foo<b>(); // Compiles
foo<g>(); // Doesn't compile
}
The error from the last (with GCC) is:
test.cc: In function 'int main()':
test.cc:12:13: error: the value of 'g' is not usable in a constant expression
foo<g>(); // Doesn't compile
^
test.cc:3:16: note: 'g' was not declared 'constexpr'
char const g[] = "Gamma";
^
I may have missed the significance of the example in the earlier discussion, because I believed that it could not have been just linkage which differentiated foo<a>
from foo<g>
- however, I have begun to doubt that position.
- Is it really the linkage, or is it some other attribute granted by
extern
, that allowsfoo<a>()
? - What is the rationale for allowing
foo<a>()
but notfoo<g>()
? In particular, if it is determined by linkage, why should internal linkage cause a variable not to be usable as a constant expression when the same variable declaredextern
would be usable? - It was suggested that the question of the symbol being visible (or not) to the linker is relevant here. To me, it seems that the fact the
foo<b>
variant is still allowed even whenstatic
is added disproves this - or am I mistaken? - (The difference between
foo<b>()
andfoo<g>()
is adequately covered by other questions, I think).