Hi everybody, please see https://gerrit.vesnicky.cesnet.cz/r/#/c/300/1 for reference.

---

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

Attachment: template_test.txz
Description: application/xz-compressed-tar

Reply via email to