1

In "header.h"

template <typename T> struct Foo
{
    void func();
};

In "Source2.cpp"

#include "Header.h"
#include <iostream>

template <typename T>
void Foo<T>::func()
{
    T a = 5;
    std::cout << a;;
}

In "Source1.cpp"

#include "Header.h"

template struct Foo<int>;

int main()
{
    Foo<int> b;
    b.func();
}

Linker error: LNK2019 unresolved external symbol "public: void __thiscall Foo::func(void)" (?func@?$Foo@H@@QAEXXZ) referenced in function _main

Is this not the right way to explicitly instantiate a class?

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • are you compiling correctly? – Mikdore May 24 '20 at 20:44
  • 1
    the definition of *func* must be in the header file, not only its declaration – bruno May 24 '20 at 20:44
  • @bruno I thought explicit instantiation is a method you can use to not have the definition in the header file – Zebrafish May 24 '20 at 20:45
  • 1
    You need to put the explicit instantiations after the method implementation in `Source2.cpp`. – cigien May 24 '20 at 20:47
  • @cigien I see, why is it not working the way I have it? – Zebrafish May 24 '20 at 20:48
  • Think about what happens when you compile the TU containing `Source2.cpp`. There is no instantiation of the method anywhere, so it simply never gets generated. Also, this makes the explicit instantiation in `Source1.cpp` redundant. – cigien May 24 '20 at 20:51
  • @Zebrafish look at my answer (hopping it is clear for you) – bruno May 24 '20 at 20:54
  • @bruno But it doesn't have to go into the header file, there are methods to have the definitions in a cpp file, one is explicit instantiation – Zebrafish May 24 '20 at 20:55
  • @cigien If I explicitly instantiate like I did in "Source1.cpp" doesn't it create an int version of the struct in "Source1.cpp"? – Zebrafish May 24 '20 at 20:59
  • Yes, it does, but the `int` instantiation of the struct doesn't have a definition of the method. – cigien May 24 '20 at 21:02
  • @cigien I see. Why does it only create the int version of the function if the class is instantiated in the same cpp that the function is defined in? I expected that by explicitly instantiating the class in "Source1.cpp" that the function in "Source2.cpp" is instantiated, to int, and that the linker would find it in that cpp. – Zebrafish May 24 '20 at 21:07
  • No, when compiling `Source2.cpp` it's as if `Source1.cpp` *doesn't exist at all*. No code in `Source1.cpp` is involved in the compilation of `Source2.cpp`, so the compiler *couldn't* know that an `int` instantiation is needed by some other TU (it's certainly not going to instantiate any thing more than it needs to). So the linker never gets the appropriate definition to link. – cigien May 24 '20 at 21:12
  • [Demo](https://onlinegdb.com/B1ELEPOjI) with `template struct Foo;` in Source2.cpp – Jarod42 May 24 '20 at 21:22

1 Answers1

-1

The definition of the template methods must be placed in the header file with the associated class allowing the compiler to 'expand' them (I use 'expand' to simplify, a template method is not a macro)

so in Header.h :

#include <iostream>
template <typename T> struct Foo
{
    void func();
};

template <typename T>
void Foo<T>::func()
{
    T a = 5;
    std::cout << a;
}

In "Source1.cpp"

#include "Header.h"

template struct Foo<int>;

int main()
{
    Foo<int> b;
    b.func();
}

Compilation and execution (a std::cout << std::endl; is missing to be sure to flush and write a newline) :

pi@raspberrypi:/tmp $ g++ Source1.cpp 
pi@raspberrypi:/tmp $ ./a.out
5pi@raspberrypi:/tmp $ 

Do not be afraid of 'multiple' definitions of func because you use the same instantiation in several files, the compiler/linker manages that for you

bruno
  • 32,421
  • 7
  • 25
  • 37