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 declaredexternwould 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 whenstaticis added disproves this - or am I mistaken?
- (The difference between foo<b>()andfoo<g>()is adequately covered by other questions, I think).
 
     
     
    