3

I have a linker issue when trying to explicitly instantiate a class. Using C++11, LLVM 5.1 . Here is a minimal working example:

declaration.h :

template <class T>
class Box {
    public :
    template <class _T>
    using Box_sub = Box<_T>;
};

//argument 'int N' is only used to remove ambiguity about class instantiation
template < template <class T> class Tbox, int N >
class A {
    public :
    A();
};

A_implementation.h :

template < template <class T> class Tbox, int N >
A<Tbox,N>::A() {}

explicit_instantiation.cpp :

#include "declaration.h"
#include "A_implementation.h"

template class A<Box,1>;
template class A<Box<int>::Box_sub,2>;

main.cpp :

#include "declaration.h"

int main() {

    A<Box,1> a1;
    A<Box<int>::Box_sub,2> a2;
    return 0;
}

And here is the linker error :

Undefined symbols for architecture x86_64:
"A<Box<int>::Box_sub, 2>::A()", referenced from:
  _main in main.o

Looks like compiler consider the second explicit instantiation as something different than main's second declaration. I don't see why. Probably a problem as with class template being embedded in another one.

Actually the problem is probably closely linked to another, as I previously asked about dynamic casting : C++ dynamic downcasting to class template having template template parameter being a class template or an alias template

A trick was proposed, but in the case of explicit instantiation I was wondering if another (simpler) trick was possible.


Solution given in comments : it is a bug in Clang 3.4

Community
  • 1
  • 1
brahmin
  • 568
  • 1
  • 5
  • 17
  • How are you compiling everything? I can't reproduce. – Barry Nov 05 '15 at 21:04
  • 1
    FYI, LLVM 5.1 is Apple's versioning, and is really [LLVM 3.4](https://en.wikipedia.org/wiki/Xcode#Toolchain_versions). Try a newer version of LLVM, as it could be an old bug. – Cornstalks Nov 06 '15 at 15:42
  • Ok sorry about that, I'm always confused about Apple's compiler versioning. Thing is, to my knowledge, it's quite hard to change llvm version without updating to a new Xcode, and therefore updating to a new max os X. I could do that, but 10.9 isn't that old. So even if it fixes the problem, there are good chances that some people cannot compile my code on their system. Also, the problem is likely to come from C++ standards being enforced on LLVM and not GCC about this particular issue (see link in the post). So, not sure a newer version of LLVM would change this. – brahmin Nov 06 '15 at 15:49
  • 1
    Upgrading Xcode will likely fix your issue, as I just tried this and it compiled and ran (with no warnings or errors with `-pedantic -Wall -Wextra -std=c++11`) with Xcode 7.1. – Cornstalks Nov 06 '15 at 15:59
  • 1
    The problem is reproducible on Clang 3.4 and lower, and appears to have been fixed in Clang 3.5. Clang 3.4 issues a bogus warning, `function 'A::Box_sub, 2>::A' has internal linkage but is not defined`, which doesn't make sense. It also works fine in GCC 5.2. Everything points to a bug in older Clang versions. This has to work; as explained in the linked answer, it wouldn't work if you tried to explicitly instantiate `A::Box_sub,2>` and then use `A` (or vice versa) - `Box` and `Box::Box_sub` are different templates, making the two specializations different. – bogdan Nov 06 '15 at 16:33
  • 1
    Ok problem fixed with Xcode 7.1. Can't select best answer though, so in place: thanks to you – brahmin Nov 16 '15 at 00:48

1 Answers1

1

Solution given in comments : it is a bug in Clang 3.4

brahmin
  • 568
  • 1
  • 5
  • 17