Disclaimer: I know that templates are usually implemented in the header file. Please read through.
I have a C++ template-related issue. My code builds with MSVC under Windows but doesn't with LLVM-Clang under Mac OSX, but I'm not sure which one is wrong.
Here is a simple test case, composed of three source files:
main.cpp
#include "templ.h"
int main()
{
templ(1);
return 0;
}
templ.h
template<typename T>
T templ(const T&);
templ.cpp
#include "templ.h"
template<typename T>
T templ(const T& t)
{
return t;
}
//explicit instantiation
template int templ(const int&);
//implicit instantiation
void f()
{
templ(1);
}
As you can see, I want the implementation of the function template to be private (i.e. hidden in the .cpp file). To allow this, I must instantiate my template in the same translation unit as its definition. In the above example, I only instantiate templ<int>
. AFAIK, this is unusual, but perfectly cromulent C++.
As is, this code builds with both the compilers. However, if I comment out the explicit instantiation and only leave the implicit instantiation, the compilers behave differently. MSVC builds successfuly, but LLVM-Clang fails with the following linker error:
Undefined symbols for architecture x86_64:
"int templ<int>(int const&)", referenced from:
_main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
Besides, that error occurs only when the optimization is enabled (e.g. -02
).
What does the standard say about this? Is this a known behavior/bug of LLVM-Clang?
My version of LLVM-Clang is:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
Sorry if this is a duplicate. It's very hard to pick the correct keywords.
This is normal and expected.
14 Templates
6 A function template, member function of a class template, variable template, or static data member of a class template shall be defined in every translation unit in which it is implicitly instantiated (14.7.1) unless the corresponding specialization is explicitly instantiated (14.7.2) in some translation unit; no diagnostic is required.
As applied to your case, this means that when the explicit instantiation of templ
is removed, the compiler can either
templ
and not generate any externally usable entity. Either behaviour is permitted for a conforming implementation. If you make sure there's an explicit instantiation somewhere, either will produce valid object code. If you don't, you may or may not get an error and it's your own fault.
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