lundi 27 avril 2020

Linker error inheriting constructor from template class c++

Disclaimer: I use the name Vector because that's the name of the class in my project, more in the physics/math sense, it is not the same as std::vector, the class for dynamically sized arrays

Summary

In my project, I have a class Vector inherited by class Vector3D. Vector is templated with an int representing it's rank/size. Unfortunately, I am getting an error during compilation and linking (I have put the error through demangling):

Error LNK2019
unresolved external symbol "public: __cdecl Vector<3>::Vector<3>(double * const)" (public: __cdecl Vector<3>::Vector<3>(double * __ptr64 const) __ptr64 referenced in function "public: __cdecl Vector3D::Vector3D(double * const)" (public: __cdecl Vector3D::Vector3D(double * __ptr64 const) __ptr64
C:\GitRepositories\3dModeler\3dModeler\out\build\x64-Debug\3dModeler
C:\GitRepositories\3dModeler\3dModeler\out\build\x64-Debug\vectors.lib(Vector3D.cpp.obj)

As far as I can tell, it's unable to find or link the inherited constructor from Vector<3>, but I could be wrong.

My Code

Class Vector is declared in file Vector.hpp:

/*
    A generic Vector class
*/
#pragma once //aware of the debate around include guards. This is simpler for now, I think
#include <string>
template <int Rank>
class Vector {
public:
    Vector() = default;
    Vector(double vals[Rank]);                      // Constructs the vector with given values
    double dot(Vector<Rank> v);
    Vector<Rank> add(Vector<Rank> v);
    /* 
    Some other stuff...
    */
    //public member variables
    double values[Rank];
};

It is implemented in file Vector.cpp, partially pasted:

#include "Vector.hpp"

template <int Rank>
Vector<Rank>::Vector(double vals[Rank]):values(vals) {}

Class Vector3D is declared in file Vector3D.hpp:

#pragma once
#include <string>
#include "Vector.hpp"
class Vector3D: public Vector<3> {
public:
    Vector3D(Vector<3>); // NOT explicit, so can swap between them 
    Vector3D(double vals[3]);
    Vector3D cross(Vector3D crossWith); // cross product
};

Relevant parts of the implementation in Vector3D.cpp:

#include "Vector3D.hpp"
#include "Vector.hpp"
#include <cmath>
/*
    Constructs a new 3D Vector out of an array in the format {x, y, z}
*/
Vector3D::Vector3D(double vals[3]) : Vector<3>(vals) {}

/*
    Converts a rank 3 vector into a 3-dimensional vector, assuming dimenson 0 is X, 1 is y, and 2 is z
*/
Vector3D::Vector3D(Vector<3> v) : Vector3D( v.values ) {}

Build Context

I am using Visual Studio 2019. I have opted to use CMake. I am on Windows 10 x64. The file system looks something like:

lib/
 - CMakeLists.txt
 - Solid.cpp
 - Solid.hpp
 - vectors/
    - CMakeLists.txt
    - Vector.hpp
    - Vector.cpp
    - Vector3D.hpp
    - Vector3D.cpp

lib/CMakeLists.txt:

add_library (lib STATIC "Solid.cpp")
target_include_directories (lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

add_subdirectory("vectors")
target_link_libraries(lib LINK_PUBLIC vectors)

Library target lib later gets linked into my test executable. File lib/vectors/CMakeLists.txt:

add_library(vectors STATIC "Vector3D.cpp" "Vector.cpp" "Vector3D.hpp" "Vector.hpp" "vectors.hpp")
target_include_directories (vectors PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Thanks

This is a very long post. As I'm writing this I'm trying to find something to cut without losing necessary information. Thanks a lot to anybody who even finishes reading this post, let alone tries to help.

Aucun commentaire:

Enregistrer un commentaire