0

I'm asking your help because I'm using templates and it seems like I misunderstood something.

Here's my code :

arbre.h

template<typename T>
class Arbre;

template<typename T>
class Noeud
{
    friend class Arbre<T>;

    public :

    Noeud();
    ~Noeud();
    T get_info()const;

    private :
    T info;
    Noeud<T> *fg, *fd;
};

template<typename T>
class Arbre
{
    public :
    //Constructors-------------------------------------------------------------
    Arbre();
    /*
      other function definitions
    */
}

arbre.tpp

#include "arbre.h"

template <typename T>
Noeud<T>::Noeud(){
    fg = fd = 0;
}

template <typename T>
Noeud<T>::~Noeud(){
}
template <typename T>
T Noeud<T>::get_info()const{
    return info;
}

template <typename T>
Arbre<T>::Arbre(){
    racine = 0;
}
/*
  other function implementations...
*/

The main.cpp includes "arbre.h" and creates an object like so :

Arbre<int> a;

So following this article on explicit instantiation : http://www.cplusplus.com/forum/articles/14272/

I added those 2 lines at the end of arbre.tpp :

template class Noeud<int>;
template class Arbre<int>;

So that the linker can compile the code for the int version of my object in arbre.o and so I could keep the implementation (arbre.tpp) apart from the header (arbre.h). My code worked with implicit instantiation (arbre.tpp included at the end of header.h) but I wanted to keep them apart.

I wonder why does the linking fail :

g++ -o main.o -c main.cpp -Wall -g -std=c++11
g++ -o arbre.o -c arbre.tpp -Wall -g -std=c++11
g++: warning: arbre.tpp: linker input file unused because linking not done
g++ -o arbre.out main.o arbre.o 
g++: error: arbre.o: No such file or directory
Makefile:9: recipe for target 'arbre.out' failed
make: *** [arbre.out] Error 1

Do you have any idea ? I'm doing the same thing as in the article I linked aren't I ?

Thanks in advance.

Harkan
  • 153
  • 2
  • 12
  • "but I wanted to keep them apart." - why? Life is much simpler if you put the implementations of the templates in the header file. –  Nov 16 '17 at 20:58
  • I completely missed the tpp business. Either tell gcc it's a source file `-x cpp` or rename the file to the standard extension. – StoryTeller - Unslander Monica Nov 16 '17 at 21:01

3 Answers3

4

The explicit instantiation definition is not enough. Generally speaking, the compiler is supposed to assume the primary template definition is all that it sees. So to it, those specializations rely on undefined members.

However, there is the concept of an explicit instantiation declaration. It tells the compiler to look for the template definition elsewhere. Just add those two at the bottom of your header:

extern template class Noeud<int>;
extern template class Arbre<int>;
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
0

Since you are using a nonstandard extension, .tpp, you may want to tell the compiler that you are working with C++ code, g++ -x c++.

Eljay
  • 4,648
  • 3
  • 16
  • 27
0

File with template definition can not be compile separately and link. just try with the following:-

At the top of your main.ccp file include "arbre.tpp" like a header file, and compile only the main.cpp file and generate the exe.

In your main.cpp

#include"arbre.tpp"

$g++ main.cpp -o test
$./test (to run the application)
Abhijit Pritam Dutta
  • 5,521
  • 2
  • 11
  • 17
  • They can be compiled separately and I managed to do it with explicit instantiation. What you're suggesting is using implicit instantiation which I've already tried and succeeded, but not what I was looking for. Thanks for trying to help me anyway. – Harkan Nov 17 '17 at 16:15