Undefined reference to function defined in another HPP file

Hello All,
My project directory is as follows -

DIR
    * main.cpp
    * test.hpp
    * test.cpp

And code in the above mentioned files is as follows -
main.cpp -

#include <opencv2/opencv.hpp>
#include "test.hpp"

int main()
{

   std::vector<float> A{10, 100};
   std::vector<float> B{10, 100};
   std::vector<float> C{10, 100};

   add(A, B, C);
}

test.hpp -

#ifndef TEST_HPP
#define TEST_HPP
#pragma once

#include <iostream>
#include <vector>
#include <cassert>

template<typename T>
void add(std::vector<T> A, std::vector<T> B, std::vector<T> C);


#endif

and test.cpp -

#include "test.hpp"


template<typename T>
void add(std::vector<T> A, std::vector<T> B, std::vector<T> C)
{
    assert(A.size() == B.size());
    assert(B.size() == C.size());

    for(int i=0; i < 100; i++)
        C[i] = A[i] + B[i];
}

CMakeLists.txt -

cmake_minimum_required(VERSION 3.15)

project(cudaTest CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CUDA_STANDARD 14)

find_package(CUDAToolkit REQUIRED)
find_package(OpenCV REQUIRED)

#add_library(cudaLib STATIC kernels.cu kernels.cuh)
#set_target_properties(cudaLib PROPERTIES CUDA_ARCHITECTURES "75")
#target_link_libraries(cudaLib CUDA::cudart ${OpenCV_LIBS})

add_executable(exe main.cpp test.hpp test.cpp)
#add_dependencies(exe cudaLib)
target_link_libraries(exe  ${OpenCV_LIBS})

However, upon compilation, I get the following linker error,

/usr/bin/ld: CMakeFiles/exe.dir/main.cpp.o: in function `main':
main.cpp:(.text+0x1c8): undefined reference to `void add<float>(std::vector<float, std::allocator<float> >, std::vector<float, std::allocator<float> >, std::vector<float, std::allocator<float> >)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/exe.dir/build.make:181: exe] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/exe.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

I did go through other similar posts, but was unable to figure out the issue. A few rudimentary checks -

  • its a .hpp file, thus extern C is not required
  • same function definitions and declaration
  • All the required files are added in add_executable

What exactly am I doing wrong,

TIA

This is not at all a CMake problem, but a wrong usage of C++ templates.

To enable the compiler to instantiate the templates when needed (i.e. in your case during compilation of main.cpp), the definition of templates must be available. So, the definition of add must be in test.hpp file rather than in the test.cpp file.

The other option is an explicit template instantiation for float in test.cpp with an extern declaration in test.hpp. Not the usual template usage, however.

There’s an in-depth explanation of this in a canonical question on StackOverflow