1

EDIT Thanks to user Richard Critten, this issue boiled down to Templates, and my understanding of how they work. I had to move function implementations into the class header, otherwise they would not be compiled for some arbitrary type. See Why can templates only be implemented in the header file?


I'm writing a template class, Tensor, which can be ininitalised to hold elements of type T, whose constructors takes some arguments.

I've found that if I try to create an object of class Tensor in any other file, it fails with undefined reference. I made sure that I'm including the header correctly, and even created a function unrelated to the class called test_boi() which can be called successfully by other files.

I won't go into the details of my testing setup, but I have a MWE with 3 files: tensor.cpp, tensor.h, and main.cpp. In tensor.cpp I have a main() which works when uncommented. It is identical to the one in main.cpp, which fails with the undefined reference error.

For building (with CMake), I make a library using tensor.h and tensor.cpp and add it to my executable. I think this might be my problem, but I'm not sure what I'm doing wrong. Making libraries is something I've just started doing, and there's a deluge of info out there.

The fact that I am able to call test_boi() from Main.exe (when I don't create objects) tells me that tensor.cpp has been compiled, and is accessible by Main.exe. The fact that I can create these objects when I put main() in tensor.cpp tells me that there isn't something broken in my classes. "Undefined reference" stackoverflow posts are rampant, so I haven't been able to find anything that fits my particular issue.

Relevant portion of my CMake script

add_library (libTensor tensor.h tensor.cpp)

add_executable(Main.exe test_main.cpp)
target_link_libraries(Main.exe libTensor)

#add_executable (Tensor.exe tensor.cpp)
#target_link_libraries (Tensor.exe Tensor)

My Class definition (tensor.h)

#ifndef TENSOR_H
#define TENSOR_H
#include <vector>

template<typename T>
class MyClass
{
  int width, height;
 public:
  MyClass(int n, int m)
  {
    height = n;
    width = m;
  };
  MyClass(int n, int m, std::vector<T> elems);
};

int test_bois();
#endif

My function implementations (tensor.cpp) ```

#include <iostream>
#include "tensor.h"

template<typename T>
Tensor<T>::Tensor(int n, int m)
{
  //  shape = (height, width);
  height = n;
  width = m;
}

template<typename T>
Tensor<T>::Tensor(int n, int m, std::vector<T> elems)
{
  //  shape = (height, width);
  height = n + 100;
  width = m + 100;
}

int test_bois()
{
  return 42;
}

// int main()
// {
//   std::vector<int> elems(10);
//   int height = 2;
//   int width = 2;
//   Tensor<int> *my_obj_zero = new Tensor<int>(height, width);
//   Tensor<int> *my_obj_one= new Tensor<int>(height, width, elems);
//   std::cout << my_obj_zero->shape() << std::endl;
//   std::cout << my_obj_one->shape() << std::endl;
//   std::cout << "Hello World!!" << std::endl;
//   return 0;
// }

main.cpp

#include <iostream>
#include "tensor.h"

int main()
{
  std::cout << test_boi() << std::endl;

  // this block commented out to get successful run
  std::vector<int> elems(10);
  int height = 2;
  int width = 2;
  Tensor<int> *my_obj_zero = new Tensor<int>(height, width);
  Tensor<int> *my_obj_one= new Tensor<int>(height, width, elems);
  std::cout << my_obj_zero->shape() << std::endl;
  std::cout << my_obj_one->shape() << std::endl;
  std::cout << "Hello World!!" << std::endl;

  return 0;
}
Prunus Persica
  • 1,173
  • 9
  • 27

0 Answers0