Consider the following code:
#include <iostream>
template<class T>
struct foo {};
template<>
struct foo<int> {
static constexpr char value[] = "abcde";
};
template<class T>
struct bar {
static constexpr char value[] = "abcde";
};
template<class T>
struct baz {
static constexpr int value = 12345;
};
int main() {
char c = foo<int>::value[2];
char d = bar<int>::value[2];
int e = baz<int>::value;
std::cout << c << d << e << "\n";
}
When compiling with: clang++ -std=c++14 ./test_foo.cc
, I got linker error for undefined symbols: bar<int>::value
and foo<int>::value
. When I change to clang++ -std=c++17
, then only one undefined symbol: foo<int>::value
. My clang++ version is 5.0.
However, when I tried g++ -std=c++14 ./test_foo.cc
, compile succeeded. My g++ version is 5.4.0.
I have precisely 2 things to ask.
1) From the C++ standard viewpoint, which compiler behaves correctly ?
I have googled and read many cppreference pages, but haven't found anything really related to this phenomenon. Especially for the clang++ with -std=c++17
, the behave is really bizarre, since bar<int>
got passed but foo<int>
failed, the only difference is that foo<int>
is a specialization. And I read from http://en.cppreference.com/w/cpp/language/constexpr that
A constexpr specifier used in a function or static member variable (since C++17) declaration implies inline.
Thus there seems no reason for template specialization foo<int>
to fail. Furthermore, I looked at the generated object file before linking, the access to foo<int>::value[2];
is not done at compile time as one would expect it to be. I highly suspect there is something wrong in the clang++ compiler.
2) How to deal with this clang++ linking error ?
I tried something like Undefined reference to static constexpr char[], but finally I couldn't find any way to overcome this linking error. So I just wonder whether there is a way to get this linking succeed.