2

In the code bellow is listed example of forward declaration of constant template variables which compiles on both clang and gcc:

template<class T>
extern const T value;
template<class T>
const T value= 0;

auto test = value<int>;

template<class T>
extern const T value2;
template<class T>
constexpr T value2 =0;

auto test2 = value2<int>;

template<class T>
extern const T value3;
template<class T>
inline constexpr T value3 =0;

auto test3 = value3<int>;

Nevertheless if I declare the variables non const, gcc produces a linker error:undefined reference to value4<int> and undefined symbol value5<int>, but clang accepts the code:

template<class T>
extern T value4;
template<class T>
T value4= 0;

auto test4 = value4<int>; //gcc linker error

template<class T>
extern T value5;
template<class T>
inline T value5=0;

auto test5 = value5<int>; //gcc linker error

Initially I was confident all those uses cases where standard compliant. But because gcc produces a linker error for the last two cases, I was wondering if any of these forward declarations were legal? Is gcc wrong or am I on a no diagnostic required error? May a forward declaration followed by an inline definition of template variables as value3 or value5 in multiple translation unit cause odr violation?

Linking phase error demonstration


Note: In this answers to this questions it seems they have overlooked the possibility to declare the variable as an extern const.

Oliv
  • 17,610
  • 1
  • 29
  • 72
  • Can you show the actual code and what is in which file? Or is this exactly the code that fails with clang? – Matthieu Brucher Nov 28 '18 at 11:21
  • @MatthieuBrucher Nothing more than that, maybe you can add `int main(){}` if you don't like the undefined reference to main error. – Oliv Nov 28 '18 at 11:23
  • Well, godbolt accepts the code, so that's why I'm asking. – Matthieu Brucher Nov 28 '18 at 11:23
  • @MatthieuBrucher Because godblot does not perform the link phase. – Oliv Nov 28 '18 at 11:25
  • @MatthieuBrucher You can see the error [here](http://coliru.stacked-crooked.com/a/af8c33f258ab57c7) – Oliv Nov 28 '18 at 11:27
  • Good point... I saw it while playing a little bit more. Still, there is no concrete symbol, so gcc is probably right. – Matthieu Brucher Nov 28 '18 at 11:30
  • @MatthieuBrucher What do you mean by *concrete symbol*? – Oliv Nov 28 '18 at 11:31
  • The symbol itself, that should be "exported" (as the extern would imply), but then I suppose "Unless a variable template was explicitly specialized or explicitly instantiated, it is implicitly instantiated when a specialization of the variable template is used." this would mean gcc should have created the symbol? it was used int he assignment and should have been created there, shouldn't it? – Matthieu Brucher Nov 28 '18 at 11:33
  • Seems [bug 83342](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83342). – xskxzr Nov 28 '18 at 14:54
  • @xskxzr Thank you. – Oliv Nov 28 '18 at 19:09

0 Answers0