4

I am trying to code a toy program to exercise C++, but I got a weird undefined reference error that I can not solve.

My code consists of 3 file:

ex13_6.h:

#include<vector>

namespace ex13_6 {
    template<class T> class Cmp {
    public:
        static int eq(T a, T b) {return a == b;}
        static int lt(T a, T b) {return a < b;}
    };

    template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v);
}

ex13_6.cpp

#include<vector>
#include"ex13_6.h"

namespace ex13_6 {
    template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v) {
        int s = v.size();
        T swap;
        for (int i=0; i<s; i++) {
            for (int j=0; j<s; j++) {
                if (C::lt(v.at(j), v.at(i))) {
                    swap = v.at(i);
                    v.at(i) = v.at(j);
                    v.at(j) = swap;
                }
            }
        }
    }
}

main.cpp:

#include"ex13_6.h"
#include<iostream>
#include<vector>

using namespace std;
using namespace ex13_6;

int main() {
    // Sort using default comparison for int
    vector<int> v_int;
    for (int i=0; i<10; i++) {
        v_int.push_back(10-i);
    }
    bubble_sort(v_int);
    cout << "sort of int vector:\n";
    for (vector<int>::const_iterator it = v_int.begin(); it != v_int.end(); it++) {
        cout << ' ' << *it;
    }
    cout << '\n';
}

And I am compiling using:

g++ main.cpp -o main -std=gnu++0x ex13_6.cpp

Here is the error message:

/tmp/ccRwO7Mf.o: In function `main':
main.cpp:(.text+0x5a): undefined reference to `void ex13_6::bubble_sort<int, ex13_6::Cmp<int> >(std::vector<int, std::allocator<int> >&)'
collect2: ld returned 1 exit status

I really appreciate any help!

hyde
  • 60,639
  • 21
  • 115
  • 176
user690421
  • 422
  • 1
  • 5
  • 15
  • 4
    You either need an explicit template instantiation in `ex13_6.cpp`, or you should move the implementation of the template function into the header file `ex13_6.h`. See: http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – jxh Apr 30 '13 at 20:16
  • Thank you @user315052. But why can not I put the general template function definition in ex13_6.cpp? – user690421 Apr 30 '13 at 20:18
  • @user690421: You can, but you will need an explicit instantiation, as I explained. See the referenced SO question. – jxh Apr 30 '13 at 20:19
  • @JesseGood Thanks. It makes sense now. Although this sounds like a inelegant feature of C++ – user690421 Apr 30 '13 at 20:20

3 Answers3

3

Move your implementation of the bubble_sort template into your header file.

Templates are not like generics from Java, all the magic happens at compile time in C++. In order for the compiler to generate the code for each template instantiation, it must be visible, and to do that, it must be in the header (or some other file) and included in each translation unit that uses it.

Collin
  • 11,977
  • 2
  • 46
  • 60
1

Your templated function definition should be in the ex13_6.h file:

#include<vector>

namespace ex13_6 {
    template<class T> class Cmp {
    public:
        static int eq(T a, T b) {return a == b;}
        static int lt(T a, T b) {return a < b;}
    };

    template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v) {
        int s = v.size();
        T swap;
        for (int i=0; i<s; i++) {
            for (int j=0; j<s; j++) {
                if (C::lt(v.at(j), v.at(i))) {
                    swap = v.at(i);
                    v.at(i) = v.at(j);
                    v.at(j) = swap;
                }
            }
        }
    }
}
antoyo
  • 11,097
  • 7
  • 51
  • 82
0

You need to put the template implementation in the header file.

When instantiating a template the compiler needs to "see" the implementation, so if you just include the header, the implementation needs to be there.

Don't include a .cpp file.

Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185