1

I am just starting out with C++, and ran into this problem. I have a class Fifo defined in Fifo.h:

/* Fifo.h */
#ifndef FIFO_H_
#define FIFO_H_

#include <atomic>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

template <class T>
class Fifo
{
public:

   Fifo<T>(int len);
   ~Fifo<T>();

   int  AddTokens(T* buffer, int len);
   int  RetrieveTokens(T* buffer, int len);

private:
   //int len;

};

#endif /* FIFO_H_ */

And the definitions in Fifo.cpp:

/* Fifo.cpp*/
#include "Fifo.h"

template <class T>
Fifo<T>::Fifo(int len)
{
  //_fifoptr = new FifoImpl_class((T)len);
  printf ("From the constructor\n");
  //thisbuffer = malloc(sizeof(T)*len);
}


template <class T>
Fifo<T>::~Fifo() { }

template <class T>
int Fifo<T>::AddTokens(T* buffer, int len)
{
  printf("Added tokens\n");
  return(1);
}


template <class T>
int Fifo<T>::RetrieveTokens(T* buffer, int len)
{
  printf("Removed tokens\n");
  return(2);
}

And, I test my class like this (Fifotest.cpp):

#include "Fifo.h"
int main(int argc, char *argv[])
{
  Fifo<int> MyFifo(20);
}

Building it with gcc-4.5 gives me this error: undefined reference to Fifo<int>::~Fifo()' undefined reference toFifo::Fifo(int)'

Looks like I have the relevant methods defined, but I am not able to figure out why I get this error. I spent time googling for it, and the option was to take a running class and modify it. But then, I want to know what is wrong with what I already have. Would appreciate any help!

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
devendra rai
  • 135
  • 12

3 Answers3

2

If you put template definition in cpp file, the definitions will not be available outside that cpp file. When you include Fifo.h from Fifotest.cpp, the compiler sees the declaration of your template class, but it does not see the implementation of the methods. Once you move them to the Fifo.h header, everything should compile.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Well, you can. You can put whatever you like wherever you like. C++ doesn't give a monkeys what your file extensions are. It just causes errors in most scenarios when you use the conventional inclusion idiom. – Lightness Races in Orbit Dec 26 '11 at 13:01
  • I think you missed my point. There are plenty of scenarios where it will work just fine. That you wrote the definition in "a cpp file" is not the critical issue; that the definition is not visible to other TUs is. Causally linked, yes, but not equivalent! – Lightness Races in Orbit Dec 26 '11 at 13:05
2

2 points:

  • The constructor is declared erroneously.

    Fifo<T>(int len); //wrong
    Fifo(int len);    //right
    
  • Templates should be defined in the same translation unit in which they are used, so having separate .h and .cpp files usually doesn't work for templates(see, for example, this question). Please move the contents of your cpp file to the header file and you should be fine.

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Actually, I'm fairly sure that they're both correct- `Fifo` and `Fifo`. But I might be wrong. – Puppy Dec 26 '11 at 13:03
  • 1
    Me too. `Fifo` in that context is a synonym for `Fifo` and there's no template ctor being declared. But I didn't try it either. – Lightness Races in Orbit Dec 26 '11 at 13:04
  • @Tomalak: Well, Fifo is indeed a synonym for Fifo but it is an injected class name which means it's as though a public member of the base class. So I'm inclined to believe you can't declare a constructor like that (I may be wrong though) – Armen Tsirunyan Dec 26 '11 at 13:06
  • Note though that this [won't work in an out-of-line _definition_](http://codepad.org/vyfV9RTn), because then the `template ` prelude tries to make the ctor a function template, which obviously cannot work. – Lightness Races in Orbit Dec 26 '11 at 13:08
  • @Tomalak: You did what? We aren't talking about whether a particular implementation supports it. We are thinking whether is it allowed standardwise – Armen Tsirunyan Dec 26 '11 at 13:08
  • @ArmenTsirunyan: Now I did try it, quite obviously. OK, so it's not a standards proof, but it's not bad... and it lends more credibility to your being wrong than to your being right. – Lightness Races in Orbit Dec 26 '11 at 13:09
  • http://stackoverflow.com/questions/8636094/is-it-valid-to-write-the-template-types-parameter-list-in-a-constructor-declara – Lightness Races in Orbit Dec 26 '11 at 13:12
  • @Tomalak: LOL http://stackoverflow.com/questions/8636098/can-the-declaration-of-a-constructor-of-a-class-template-include-template-argume – Armen Tsirunyan Dec 26 '11 at 13:13
  • Thanks a lot to everyone for help. I included "Fifo.cpp" in "Fifo.h", as was discussed in http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file. Well, obviously, having the implementation also in the header file seems like a very bad design practice, since I would not like to share my implementation. To this end, I read up the PIMPL technique, which may answer, but so far, I have had no luck in having neatly separated header and implementation, and templates put together. Any nice tutorials? – devendra rai Dec 26 '11 at 18:10
  • @devendrarai: Sorry, but there's just no good way to avoid sharing the implementation in case of templated. There are some workarounds but they aren't universal and are a real pain in the ass. Just accept that in case of generic code you'll have to share your implementation – Armen Tsirunyan Dec 26 '11 at 18:13
0

You should provide the definitions in the header file. export keyword exists in the standard but usual compilers haven't implemented it.

Inbae Jeong
  • 4,053
  • 25
  • 38