The forward-declaring template variable will cause ld error.
#include <iostream>
template<class T> extern int a;
template<class T> int a = 1;
int main()
{
std::cout << a<int> << a<float>;
return 0;
}
$ LANG=C g++ main.cpp -o main
/usr/bin/ld: /tmp/cccOb25F.o: in function `main':
main.cpp:(.text+0x6): undefined reference to `a<int>'
/usr/bin/ld: main.cpp:(.text+0x1d): undefined reference to `a<float>'
collect2: error: ld returned 1 exit status
However, the forward-declaring variable (without template) and the forward-declaring template function works fine.
#include <iostream>
extern int a;
int a = 1;
template<class T> int b();
template<class T> int b()
{
return 2;
}
int main()
{
std::cout << a << b<int>();
return 0;
}
So, is it possible to make the forward-declaring template variable in C++ works?
EDIT:
Since clang++
works fine, maybe I accidentally found a bug of g++
?
EDIT2:
I have found a bug report about 2.5 years ago (here), which is exactly the same problem. Oh, we need a guy who could read gcc source and fix it...
You can declare default arguments for a template only for the first declaration of the template. If you want allow users to forward declare a class template, you should provide a forwarding header. If you want to forward declare someone else's class template using defaults, you are out of luck!
In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.
A forward declaration allows us to tell the compiler about the existence of an identifier before actually defining the identifier. In the case of functions, this allows us to tell the compiler about the existence of a function before we define the function's body.
A class template must be declared before any instantiation of a corresponding template class. A class template definition can only appear once in any single translation unit. A class template must be defined before any use of a template class that requires the size of the class or refers to members of the class.
This is GCC Bug 83342, which is yet to be addressed.
GCC seems to make, whether intentionally or not, the assumption that a variable template first declared with the extern
keyword in a given translation unit (TU) must have its definition in another TU (thus not even looking for it in the same TU). E.g. Clang does not make this assumption (and finds the definition and re-declaration in the same TU).
template<class T> extern int a; // extern declaration.
template<class T> int a = 1; // definition.
template int a<int>; // explicit instantiation definition for a<int> specialization.
// Clang: OK
// GCC:
// - error: explicit instantiation of 'a<int>' but no definition available
int main() {}
There is no clause in the standard that would allow the assumption that GCC makes above, and the open bug report is valid.
We may note that GCC accepts the similar and likely much more common case for function templates:
template<class T> extern void f(); // extern declaration.
template<class T> void f() {} // definition.
template void f<int>(); // explicit instantiation definition for f<int>() specialization.
// Clang: OK
// GCC: OK
int main() {}
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