C++ class template undefined reference to function

13,954

Solution 1

Your class is named wrong. Your class is named cai where all your functions belong to a class named number: http://ideone.com/ZayX0c

One more thing.. you cannot have templates in the .cpp file. Template functions/defintions go in the header along with the class declaration. This is the reason for your undefined function error. Non-template functions go in the .cpp.

#include <cstdio>
#include <cstdlib>

template <class T>
class number {
public:
    T x;
    T y;

    number (int a, int b){
        x=a; y=b;}
    int add (T&);
    T greater ();
};

template <class T>
int number<T>::add (T& rezAdd){
    rezAdd = x+y;
    return 1;
}

template <class T>
T number<T>::greater (){
        return x>y? x : y;
}


int main (int argc, char **argv) {
    int aux;
    number<int> c(3,5);

    c.add(aux);
    printf ("number added [%d]\n", c.add(aux));
    printf ("greater number: [%d]\n", c.greater());

    return 0;
}

Solution 2

I prefer to have all of my functions in the .cpp file, regardless of whether they are template functions or regular functions. And there is a way to do that with some basic #ifndef magic. Here's what you can do:

main.cpp

#include "myclass.hpp"

int main()
{
  // ...
}

myclass.hpp

#ifndef MYCLASS
#define MYCLASS

template<class T>
class MyClass
{
  T val;
public:
  MyClass(T val_);
}

#define MYCLASS_FUNCTIONS
#include "myclass.cpp"

#endif

myclass.cpp

#ifndef MYCLASS_FUNCTIONS
#include "myclass.hpp"

// regular functions:
// ...

#else

// template functions:
template<class T>
MyClass<T>::MyClass(T val_)
    :val(val_)
{}

// ...
#endif

Here's how the precompiler sees it. We have two .cpp files.

  1. When we compile main.cpp we:
    1. include myclass.hpp
    2. check that MYCLASS is undefined, and it is
    3. define it
    4. give compiler the definitions of the generated class (from template class)
    5. include myclass.cpp
    6. define MYCLASS_FUNCTIONS
    7. check if MYCLASS_FUNCTIONS is defined, it is
    8. give compiler the definitions of the generated functions (from template functions)
  2. When we compile myclass.cpp
    1. check if MYCLASS_FUNCTIONS is defined, it isn't
    2. include myclass.hpp
    3. check that MYCLASS is undefined, and it is
    4. define it
    5. give compiler the definitions of the class
    6. include myclass.cpp
    7. include myclass.hpp again
    8. this time MYCLASS is defined so do nothing inside, return to myclass.cpp
    9. check if MYCLASS_FUNCTIONS is defined, it is
    10. give compiler the definition of the generated functions (from template functions)
    11. exit include twice
    12. pass to the compiler all the regular functions

Solution 3

Move the definitions of the add and greater function templates into your number.h.

Remember that add and greater aren't functions, they're function templates. To create actual functions, the compiler has to instantiate the template for specific types, such as int, and it can only do that if it has access to the template's definition at the point where it discovers that an instance is needed.

When you compile number.cpp, the compiler has access to the templates' definitions, but it doesn't see any code that requires a specific instance (such as number<int>), so it doesn't generate instances.

When you compile resolver.cpp, the compiler sees that it needs to instantiate those templates for the int type, but it can't since it doesn't have their definitions. So it generates "external references", basically notes telling the linker to look for those functions in some other object file.

The result is that the function templates don't get instantiated in either object file — in one because the compiler didn't know that it should, and in the other because it couldn't — so when the linker goes looking for them (to resolve those external references), it can't find them. That's why you get the error.

Moving the template function definitions into the header makes them visible to the compiler while it's compiling main.cpp, so it's able to instantiate those functions for the int type. Function templates typically need to be defined in header files, rather than .cpp files, for exactly this reason.

Share:
13,954
MihaiGrad
Author by

MihaiGrad

Updated on June 23, 2022

Comments

  • MihaiGrad
    MihaiGrad almost 2 years

    I keep getting undefined reference when i call the two functions from my template class "add" and "greater" in my main function.

    So, i have: number.h

    #ifndef NUMBER_H
    #define NUMBER_H
    
    template <class T>
    class number {
    public:
        T x;
        T y;
    
        number (int a, int b){
            x=a; y=b;}
        int add (T&);
        T greater ();
    };
    
    #endif
    

    number.cpp

    #include "number.h"
    
    template <class T>
    int number<T>::add (T& rezAdd){
        rezAdd = x+y;
        return 1;
    }
    
    template <class T>
    T number<T>::greater (){
            return x>y? x : y;
    }
    

    And my main file is: resolver.cpp

    #include <stdio.h>
    #include <stdlib.h>
    #include "number.h"
    
    int main (int argc, char **argv) {
        int aux;
        number<int> c(3,5);
    
        c.add(aux);
        printf ("number added [%d]\n", c.add(aux));
        printf ("greater number: [%d]\n", c.greater());
    
        return 0;
    }
    

    The errors that i keep getting are:

    g++ -Wall -o tema1 resolver.cpp number.cpp
    /tmp/ccX483J4.o: In function `main':
    resolver.cpp:(.text+0x34): undefined reference to `number<int>::add(int&)'
    resolver.cpp:(.text+0x47): undefined reference to `number<int>::add(int&)'
    resolver.cpp:(.text+0x64): undefined reference to `number<int>::greater()'
    collect2: ld returned 1 exit status
    make: *** [all] Error 1
    

    Thanks for the help in advance!

  • MihaiGrad
    MihaiGrad about 10 years
    i edited it wrong. sorry about that.
  • Brandon
    Brandon about 10 years
    I edited the answer. Put your template implementation in the header (.h). Non-template implementations go in the body (.cpp)
  • MihaiGrad
    MihaiGrad about 10 years
    someone said to modify "number<int> c(3,5);" in main function with "number<int> c = number<int>(3, 5);" but i keep getting the errors mentioned earlier
  • Brandon
    Brandon about 10 years
    No difference in this specific case. All you need to do is move all your template functions to the header and all non-template functions to the implementation file.
  • MihaiGrad
    MihaiGrad about 10 years
    works now! thanks very much for the help
  • MihaiGrad
    MihaiGrad about 10 years
    very useful. thanks for the help!
  • Shravan40
    Shravan40 over 7 years
    Best described solution. I was exactly looking for this and found it after a month. ("It's better late than never").