gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > template: reference not found

#156794 - Maxxie - Tue May 13, 2008 11:46 pm

Hi,

i have a linking problem i can't seem to find the cause, someone might lift my blindness.

The file setup is the following:
fifo.cpp, fifo.hpp, ipc,cpp and ipc.hpp

The .cpp's are compiled with g++, their .d and .o are generated in the same /build folder.

In fifo.hpp/cpp a template is declared
Code:

#ifndef fifo_included
#define fifo_included

template <class T>
class FIFO
{
   private:
      volatile int *         head ;
      volatile int *         tail ;
      volatile int *         maxCount ;
      volatile T *         buffer ;
   public:
      FIFO(int size) ;
      ~FIFO() ;
      
      bool Push(T entry) ;
      T Pop(void) ;
      
      int Count(void) ;
      bool empty(void) ;
      bool full(void) ;
} ;

#endif



The bodies are in the .cpp like
Code:

template <class T>
bool FIFO<T>::empty(void)
{
// ...
}


They are used within ipc.cpp and should be created by "new FIFO<int>(32)", but that leads to
c:/devkitPro/projects/NeocronDS/arm7/../shared/source/ipc.cpp:35: undefined reference to `FIFO<int>::empty()'

The fifo.cpp itself is compiled without error or warning.

When examinating fifo.o, with objdump -t there is no symbol that would indicate any class in it.

What am i doing wrong?

#156796 - sniper - Tue May 13, 2008 11:55 pm

try to put the method as inline in the header file and not in the cpp file.

Code:
inline template <class T> bool FIFO<T>::empty(void)
{
// ...
}

#156799 - Maxxie - Wed May 14, 2008 12:06 am

:edit::edit:
Nope, sorry no go.

I can define them in the class body, then the error goes away, but that undermines the purpose of having multiple sourcefiles to only compile parts that changed (any change in a function body would cause recompilation of all files including the header) ... well it propably needs too :/

Defining them as "inline template", they are not passing the syntax checker.
Defining them as template <class T> inline does not solve anything

#156802 - sniper - Wed May 14, 2008 12:36 am

Oh sorry my fault. This should solve the problem??

Code:
template <class T> inline bool FIFO<T>::empty(void)
{
// ...
}


Templates are better macros and if u use it all methods must be defined in the header file.

If you want define it in the source file you have to define all possible types:

Code:

bool FIFO<int>::empty(void)
{
// ...
}

bool FIFO<char>::empty(void)
{
// ...


Edit:

GCC has not implemented the "export" for templates which is defined in the C++ standard.

Code:
export template <class T> bool FIFO<T>::empty(void)
{
// ...
}

#156804 - Maxxie - Wed May 14, 2008 12:50 am

Yes, thank you very much.

I should have thought earlier about that the templates implementation needs to be transparent to the including sources ...

#156848 - sajiimori - Wed May 14, 2008 6:49 pm

Note that while the implementations have to be visible (i.e. in the header or similar) for automatic instantiation to work (i.e. to fix your link error), you don't actually have to inline all the methods. You can remove the 'inline' keyword and the linker will strip out duplicate copies of uninlined methods.