0

I am learning about templates and am trying to transform C code into C++ code by using templates. I am getting the following error messages when I compile.

undefined reference to `void iterative_mergesort<double>(std::vector<double, std::allocator<double> >&)'

I don't know what is wrong. I've included the template methods inside the header files and rechecked my code many times. This error is vague and I don't know where to start looking.

Here is my header file:

#if !defined(__SORT_HPP_CS303)
#define __SORT_HPP_CS303

#include <vector>
using std::vector;


template <typename T> void insertion_sort (T *a, long int n);
template <typename T> void insertion_sort (vector<T> &a);
template <typename T> bool are_identical(T *a, T *b, long int n);
template <typename T> bool are_identical(vector<T> &a, vector<T> &b);


template <typename T> void recursive_mergesort (T *a, long int n);
template <typename T> void recursive_mergesort (vector<T> &a);
template <typename T> void iterative_mergesort (T *a, long int n);
template <typename T> void iterative_mergesort (vector<T> &a);
#endif

The iterative_mergesort method in sort.cpp file: Note: sort.cpp is not a class or anything, just a collection of methods.

template <typename T> void iterative_mergesort (T *a, long int n){
      T * aux = (T *) malloc(n*sizeof(T));
      for (long int size = 1; size < n; size = size + size) {
              for (long int low = 0; low < n - size; low += size + size) {
                      merge(a, aux, low, low + size - 1, min(low + size + size - 1, n - 1));
              }
      }
      free(aux);
}

template <typename T> void iterative_mergesort (vector<T> &a){
      T * aux = (T *) malloc(a.size()*sizeof(T));
      for (long int size = 1; size < a.size(); size = size + size) {
              for (long int low = 0; low < a.size() - size; low += size + size) {
                      merge(a, aux, low, low + size - 1, min(low + size + size - 1, a.size() - 1));
              }
      }
      free(aux);
}

Finally, here is the section in the main that is causing the compile error:

  t_start = std::chrono::high_resolution_clock::now();
  iterative_mergesort(a2); # this line is giving me trouble. a2
  t_end = std::chrono::high_resolution_clock::now();

Sorry for posting so much code. I tried to leave only the relevant parts here. If you need more context, please tell me.

Any help will be appreciated!

mrQWERTY
  • 4,039
  • 13
  • 43
  • 91
  • There is no definition of a2 anywhere in the code you provided. According to the error message its type is double, while you probably meant to sort some kind of container. – cababunga Nov 14 '14 at 01:51
  • 1
    `malloc` and `free` in a c++ program, yikes. You even free in the same scope - why not just use the stack? – Red Alert Nov 14 '14 at 02:05
  • http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – drescherjm Nov 14 '14 at 02:49
  • Thank you. I've accepted defube's answer as the correct one. – mrQWERTY Nov 14 '14 at 03:06

2 Answers2

4

The definition of a template, method or class, must reside entirely within the translation unit in which it is instantiated.

Move the contents of sort.cpp into your header file.

See this question for more information.

defube
  • 2,395
  • 1
  • 22
  • 34
1

Hello I figured out the problem. I had to declare the prototypes of the templates at the bottom with their expected types.

template void iterative_mergesort<double>(double*, long int);
template void iterative_mergesort<double>(vector<double> &);
template void iterative_mergesort<string>(vector<string> &);

template void recursive_mergesort<double>(double*, long int);
template void recursive_mergesort<double>(vector<double> &);
template void recursive_mergesort<string>(vector<string> &);

template void sort<double>(double*, double*, long int, long int);
template void sort<double>(vector<double> &, vector<double> &, long int, long int);
template void sort<string>(vector<string> &, vector<string> &, long int, long int);

template void merge<double>(double*, double*, long int, long int, long int);
template void merge<double>(vector<double> &, vector<double> &, long int, long int, long int);
template void merge<string>(vector<string> &, vector<string> &, long int, long int, long int);
mrQWERTY
  • 4,039
  • 13
  • 43
  • 91
  • this solution kind of defeats the purpose of using templates here - anyone who tries to use this with a new type will get the original error again. Why not just put the implementation in your header file? – Red Alert Nov 14 '14 at 02:50