I wanted to check that the extern
keyword did infact prevent class code being generated in the translation unit:
template<class> struct always_false : std::false_type {};
template <typename T> class A{
static_assert(always_false<T>::value, "If this fires, 'A' is instantiated");
};
extern template class A<int>; //error: static assertion failed: If this fires, 'A' is instantiated|
int main(){
// A<int> f;
}
Why is it that the previous code still produces an error from the static_assert
if this is my only source file? As far as I understand from the explicit use of extern
this should prevent any production of code for the class A<int>
and the linker takes care of finding a later explicit instantiation definition (in the translation unit for which the code is actually written) to match any use of A<int>
with.
However it seems that the explicit instantiation declaration is generating code in this translation unit itself as indicated by the compilation error. If I comment out extern template class A<int>
everything works fine. I was using GCC 4.9.2. but it appears clang 3.5.1 throws this error too.
Alternatively this also kicks up the same assert error:
template<class> struct always_false : std::false_type {};
template <typename T> class A{
public:
void test() { static_assert(always_false<T>::value, "If this fires, 'test()' is instantiated"); }
};
extern template void A<int>::test();
int main(){
A<int> a;
a.test();
}
Here I would've expected the member function A<int>::test()
to not even be instantiated and again wait until linking before "finding" code for the function, but it looks like the code is generated in the same translation unit. However if I take out the static_assert
:
template <typename T> class A{
public:
void test() { }
};
extern template void A<int>::test();
int main(){
A<int> a;
a.test();
}
Then I get the error I'm expecting, indicating that A<int>::test()
is not instantiated and there was a linker error:
**undefined reference to `A<int>::test()'|**
Why would the static_assert
throw an error if test()
was never instantiated?