views:

2993

answers:

4

I have a function declared like so:

template <typename T> 
T read();

and defined like so:

template <typename T>
T packetreader::read() {
    offset += sizeof(T);
    return *(T*)(buf+offset-sizeof(T)); 
}

However, when I try to use it in my main() function:

packetreader reader;
reader.read<int>();

I get the following error from g++:

g++ -o main main.o packet.o
main.o: In function `main':
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()'
collect2: ld returned 1 exit status
make: *** [main] Error 1

Can anyone point me into the right direction?

edit:

As a response to strager / Vadim:

Would it be a good idea for me to move my packet.cpp code into packet.h and rename it to something like "packet.hpp" as i've often seen used in boost?

+5  A: 

You need to use the export keyword. However, I don't think G++ has proper support, so you need to include the template function's definition in the header so the translation unit can use it. This is because the <int> 'version' of the template hasn't been created, only the <typename T> 'version.'

An easy way is to #include the .cpp file. However, this can cause problems, e.g. when other functions are in the .cpp file. It will also likely increase the compile time.

A clean way is to move your template functions into its own .cpp file, and include that in the header or use the export keyword and compile it separately.

More information on why you should try and put template function definitions in its header file (and ignore export altogether).

strager
Would it be a good idea for me to move my packet.cpp code into packet.h and rename it to something like "packet.hpp" as i've often seen used in boost?
Daniel
@Daniel, Only if all your functions are template functions. Otherwise, you can get away with moving some of your functions over and keeping the .cpp file.
strager
+4  A: 

The best practice with template functions is to define them in header files. They are created at compile time so compiler has to have definition around to do so.

When export for templates would be more supported this wouldn't be the case though but right now it still hardly can be used.

vava
I don't recommend using `export`. According to http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14, it's been voted out of the C++0x standard.
uckelman
+2  A: 

The problem is that a function template is not a function. It's a template for creating functions as needed.

So for a template to work, the compiler intuitively needs two pieces of information: The template itself, and the type that should be substituted into it. This is unlike a function call, which the compiler can generate as soon as it knows that the function exists. It doesn't need to know what the function does, just that it looks like void Frobnicate(int, float), or whatever its signature is.

When you declare the function template without defining it, you're only telling the compiler that such a template exists, but not what it looks like. That's not enough for the compiler to be able to instantiate it, it has to be able to see the full definition as well. The usual solution is to put the entire template in a header that can be included where needed.

jalf
A: 

Is their any compiler support template separate compilation?

As I know the common practice is declare and implement template functions in the header file

lz_prgmr
Comeau does I believe. And modern version of MSVC *might* but I haven't checked that myself.
vava
The latest VS2008 doesn't support export keyword yet. seems MS guys reserved this keyword for future support: warning C4237: 'export' keyword is not yet supported, but reserved for future use
lz_prgmr