---
Attached is a stripped-down testcase of the PartVisitor template used in trojita.
$ tar -xJf template_test.txz $ cd template_test $ g++ -o test main.cpp class.cpp # this should have worked nicely, where $ clang++ -o test main.cpp class.cpp # will fail:/tmp/main-675143.o:(.rodata._ZTV8TemplateIiE[_ZTV8TemplateIiE]+0x8): undefined reference to `Template<int>::~Template()' /tmp/main-675143.o:(.rodata._ZTV8TemplateIiE[_ZTV8TemplateIiE]+0xc): undefined reference to `Template<int>::~Template()' clang: error: linker command failed with exit code 1 (use -v to see invocation)
# Now try
$ clang++ -DHELP_CLANG=1 -o test main.cpp class.cpp
# Yeaḥh!
clang version 3.5.0 (tags/RELEASE_350/final)
gcc (GCC) 4.9.2
The reason is the additional
#if HELP_CLANG
template<typename Type> Template<Type>::~Template()
{
}
#endif
in main.cpp
You may add as many
template class Template<int>;
as ever you like and wherever you want - clang won't compile, while gcc is
happy with the one implementation in class.cpp and no explicit instatiation
at all. (Notice that multiple explicit instatiations are ill-formatted and
both compilers will complain about that ;-)
The reason is (likely) the way ld is invoked by either - clang++ calls ld directly whereas g++ invokes collect2 [1]
As far as I understand this behavior, clang++ will effectively require an inline implementation of the destructor, resp. in every relevant source file.
As as workaround, this could happen by
#if __clang__
virtual ~FooBar() {}
#else
virtual ~FooBar();
#endif
and
#ifndef __clang__
template <typename Foo> FooBar<Foo>::~Foo() {}
#endif
in the source.
Cheers,
Thomas
[1] http://gcc.gnu.org/onlinedocs/gccint/Collect2.html
template_test.txz
Description: application/xz-compressed-tar
