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.
extern
, that allows foo<a>()
?foo<a>()
but not foo<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 declared extern
would be usable?foo<b>
variant is still allowed even when static
is added disproves this - or am I mistaken?foo<b>()
and foo<g>()
is adequately covered by other questions, I think).GCC bug.
N3337 (which is C++11 + editorial fixes) [temp.arg.nontype]/2 has an example that's directly on point:
template<class T, const char* p> class X {
/* ... */
};
X<int, "Studebaker"> x1; // error: string literal as template-argument
const char p[] = "Vivisectionist";
X<int,p> x2; // OK
In C++03 reference/pointer template arguments are limited to things with external linkage, but that restriction was removed in C++11.
The rules for reference/pointer template arguments are relaxed in C++17 to permit all constant expressions, so probably the reason why GCC accepts the example with -std=c++1z
is that it goes through a different code path in that mode.
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