1

I'm learning C++ and using CLion to build projects. I have the main.cpp file in the main directory. I also have a main/Objects directory, inside of which I have Vec3.h and Vec3.cpp files:

//Vec3.h
template<typename T>
class Vec3
{
public:
    // 3 most basic ways of initializing a vector
    Vec3() : x(T(0)), y(T(0)), z(T(0)) {}
    Vec3(const T &xx) : x(xx), y(xx), z(xx) {}
    Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {}
    T x, y, z;

    T length();
};

.

//Vec3.cpp
#include "Vec3.h"
#include <stdio.h>
#include <math.h>

template <typename T>
T Vec3<T>::length()
{
    return sqrt(x * x + y * y + z * z);
}

.

//main.cpp
#include <iostream>
#include "Objects/Vec3.h"

int main() {
    Vec3<double> vec(3, 4, 0);
    std::cout << "Hello, World!" << std::endl;
    std::cout << vec.length() << std::endl;
    return 0;
}

.

//CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(Testing)

set(CMAKE_CXX_STANDARD 14)

set(SOURCE_FILES main.cpp Objects/Vec3.cpp)

add_executable(Testing ${SOURCE_FILES})

When I try to build and run, I get the following error:

undefined reference to "Vec3<double>::length()". ld returned 1 exit status

What info am I not giving to the linkeditor?

Kevin
  • 16,549
  • 8
  • 60
  • 74

1 Answers1

1

You haven't told CMake about your header file, so you can use target_include_directories. Add the following line to the end of your CMakeLists.txt file, to ensure the header is included in the build:

target_include_directories(Testing PRIVATE Objects)

Also, templated definitions can typically only be implemented in header files. Move the following function definition from the Vec3.cpp file to the header file (Vec3.h):

template <typename T>
T Vec3<T>::length()
{
    return sqrt(x * x + y * y + z * z);
}
Kevin
  • 16,549
  • 8
  • 60
  • 74
  • CMake now throws the following error: "target_include_directories called with invalid arguments" – Francisco José Letterio Aug 08 '19 at 13:11
  • @FranciscoJoséLetterio Updated by answer. Also, make sure you add this line to the end of your `CMakeLists.txt` file, after you've called `add_executable()`. – Kevin Aug 08 '19 at 13:16
  • Ok, with the PRIVATE added in CMake throws no errors. However, the undefined reference error persists – Francisco José Letterio Aug 08 '19 at 13:17
  • @FranciscoJoséLetterio Forgot about template definitions... In your example, `Vec3.cpp` can serve as a place-holder file, but you have to move the `length()` function definition to the header file. See the linked [answer](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – Kevin Aug 08 '19 at 13:23