-1

I have a very weird error: I have a pair of .h and .cpp files that contain some functions and constants. When I try to compile it, g++ says "undefined reference" to the function. The function prototype and definition seem to be the same. I have commented everything out except the necessary lines, and g++ still complains about it.

My program is currently (after commenting everything out):

main.cpp

#include "a.h"

int main(){
    makehex(10);

    return 0;
}

a.h

#include <iostream>
#include <sstream>

#ifndef __A___

static const std::string b = "01";
static const std::string d = b + "23456789";
static const std::string h = d + "abcdef";

template <typename T> std::string makehex(T value, unsigned int size = 2 * sizeof(T));
#endif

a.cpp

#include "a.h"

template <typename T> std::string makehex(T value, unsigned int size){
    // Changes a value to its hexadecimal string
    if (!size){
        std::stringstream out;
        out << std::hex << value;
        return out.str();
    }
    std::string out(size, '0');
    while (value && size){
        out[--size] = h[value & 15];
        value >>= 4;
    }
    return out;
}

There is only 1 function. I dont see how this could error.

Im compiling with g++ -std=c++11 main.cpp a.cpp and getting the errors:

main.cpp:(.text+0x1a): undefined reference to `std::string makehex<int>(int, unsigned int)'
collect2: error: ld returned 1 exit status

Is it because of the template? If so, how do i fix it?

calccrypto
  • 8,583
  • 21
  • 68
  • 99
  • possible duplicate of [Template issue causes linker error (C++)](http://stackoverflow.com/questions/1639797/template-issue-causes-linker-error-c) –  Jul 19 '13 at 20:03
  • You're using a [reserved identifier](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). – chris Jul 19 '13 at 20:05
  • Bad Karma: declaring static variables in a header file. – Thomas Matthews Jul 19 '13 at 20:06

3 Answers3

2

Common template mistake. The compiler needs to know the definition of the template at compile time: thus, the definition of the template function must be in the header file.

IdeaHat
  • 7,641
  • 1
  • 22
  • 53
  • 1
    Or, a specialization of the template must be implemented in the .cpp file. –  Jul 19 '13 at 20:03
  • @calccrypto What do you think `template std::string makehex(T value, unsigned int size)` is? –  Jul 19 '13 at 20:04
  • @H2CO3 Ha yeah, that is true, that screwed me up the first time i did it. – IdeaHat Jul 19 '13 at 20:04
2

You need to understand that templates aren't code themselves but it tells the compiler how to generate code that other parts of your program can use. For the compiler to be able to do that automatically it must have seen the definition of that template at the point of instantiation.

But in your existing setup, only the declaration of makehex<T>() is visible in main.cpp. The actual definition of makehex<T>() is squirreled away in a.cpp which main doesn't know about during compilation (it's in a different translation unit).The easy fix for this is to move implementation of makehex<T>() from a.cpp into a.h.

greatwolf
  • 20,287
  • 13
  • 71
  • 105
1

A template function is only emitted when you actually instantiate the template. You are attempting to do this in the main function, using the call makehex(10).

You have included "a.h" in the main.cpp file, so when compiling main.cpp, you have access to the declaration of the function. However, the compiler is not able to access the definition because it's in a different file (a.cpp) which hasn't been included.

The short-term fix is to #include "a.cpp" in main.cpp. However, the long-term fix is not to have .cpp files for template function definitions - put it all in the header (.h) file. (This does NOT apply to ordinary functions/classes etc).

maditya
  • 8,626
  • 2
  • 28
  • 28