0

I have a simple function declared in header file and defined cpp file. When I delete the test_vector function in cpp file, I got this error.

Undefined symbols for architecture x86_64:
  "void chapter3::print_vector<int>(std::__1::vector<int, std::__1::allocator<int> > const&)", 
referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64

What's going on here?

//  chapter3.hpp


#ifndef chapter3_hpp
#define chapter3_hpp

#include <stdio.h>
#include <vector>

namespace chapter3 {

template<typename T>
void print_vector(const std::vector<T>&);

}

#endif /* chapter3_hpp */

//  chapter3.cpp

#include "chapter3.hpp"
#include <iostream>
#include <vector>

using namespace std;

namespace chapter3 {

template<typename T>
void print_vector(const vector<T>& vec) {
    for(auto& elem: vec) {
        cout << elem << ' ';
    }
    cout << endl;
}

void test_vector() {
    vector<int> u(10, -1);
    print_vector(u);
}

}

//  main.cpp

#include <iostream>
#include <vector>

#include "chapter3.hpp"

using namespace std;

int main(int argc, const char * argv[]) {
    vector<int> vec {1,2,3};
    chapter3::print_vector(vec);
    
    return 0;
}

  • Template code must be placed in a header file, not in a separate cpp file. – john Aug 05 '20 at 07:33
  • @john But, why does it work when test_vector function is present? – Barış Deniz Sağlam Aug 05 '20 at 07:38
  • 1
    It's to do with *instantiation*, by using `print_vector` on a vector when compiling chapter3.cpp you force the compiler to instantiate print_vector for vector. This instantiation is then available for the linker when it links main and chapter3. As an experiment try changing `vector u(10, -1);` to `vector u(10, -1.0);` and you will see that your error comes back again. Putting the template code in the header file ensures that the template can be instantiated wherever it is needed. You won't have to rely on it being instantiated in some other file. – john Aug 05 '20 at 07:43
  • OK, now I got it, thanks. @john – Barış Deniz Sağlam Aug 05 '20 at 07:45
  • Also worth noting that the linker will clean up multiple instantiations, so that that only one instantiation (for each type) remains. – john Aug 05 '20 at 07:50

0 Answers0