So I'm trying to implement a class that encapsulates some linear algebra concepts and I had success by keeping everything to a sigle .hpp
file. However, after starting my first job, I quickly learned this isn't very professional, so I tried to separate annotated class declarations into headers and raw definitions into source files. However, when trying to compile in VS2019, I get the error LNK2019: unresolved external symbol
for some of the methods.
Now, over the years I've read multiple questions on this site and pages on Microsoft Docs about linker problems, including right now, and still I can't understand what I'm doing wrong here. I don't doubt there is an answer already somewhere here, but if there is then it's either very hard to find or in a format that's very difficult for me interpret. I tried a bunch of stuff I've seen in other more general answers as well to no avail.
Without further ado, here's my example. Briefly explaining, I define an iterator to loop over the matrix elements sequentially.
// iterators.hpp
#pragma once
#include<iterator>
struct Shape { size_t m, n; };
template<class T>
class Iterator
{
public:
using iterator_category = std::forward_iterator_tag;
Iterator(T* ptr = nullptr) : mptr{ ptr } {}
T& operator*() const { return *mptr; }
Iterator& operator++() { mptr++; return *this; }
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
friend bool operator==(const Iterator& a, const Iterator& b) { return a.mptr == b.mptr; }
friend bool operator!=(const Iterator& a, const Iterator& b) { return a.mptr != b.mptr; }
T* getPtr() const { return mptr; }
private:
T* mptr;
};
I declare a "matrix" class as a wrapper around a flat vector and do pointer arithmetic to simulate a matrix structure. (I know it reads "forward_iterator_tag
" right now in the iterator, but it's actually going to be random acess).
// matrix.hpp
#pragma once
#include<vector>
#include "iterators.hpp"
template<class T>
class Matrix
{
protected:
std::vector<T> matrix_;
Shape shape_;
public:
Matrix() = default;
Matrix(std::initializer_list<std::initializer_list<T>>);
void print();
Shape getShape() const;
void setShape(size_t m, size_t n);
Iterator<T> begin() const;
Iterator<T> end() const;
};
I define the properties of Matrix.
// matrix.cpp
#include<iostream>
#include "matrix.hpp"
template<class T>
Matrix<T>::Matrix(std::initializer_list<std::initializer_list<T>> list) { /* blah blah blah... */ }
template<class T>
void Matrix<T>::print() { /* blah blah blah... */ }
template<class T>
Shape Matrix<T>::getShape() const { return shape_; }
template<class T>
void Matrix<T>::setShape(size_t m, size_t n) { shape_.m = m; shape_.n = n; }
template<class T>
Iterator<T> Matrix<T>::begin() const { return Iterator<T>{ matrix_.begin()._Ptr }; }
template<class T>
Iterator<T> Matrix<T>::end() const { return Iterator<T>{ matrix_.end()._Ptr }; }
And then I try to run some tests.
// test.cpp
#include "matrix.hpp"
#include<iostream>
#include<algorithm>
int main()
{
Matrix<int> m;
m = { {1, 2, 3}, { 4, 5, 6 }, {7, 8, 9} };
m.print();
std::cout << m.getShape().m << " " << m.getShape().n << std::endl;
}
I'm trying to build my project in VS2019. I get the following error:
1>test3.obj : error LNK2019: unresolved external symbol "public: __cdecl Matrix<int>::Matrix<int>(class std::initializer_list<class std::initializer_list<int> >)" (??0?$Matrix@H@@QEAA@V?$initializer_list@V?$initializer_list@H@std@@@std@@@Z) referenced in function main
1>test3.obj : error LNK2019: unresolved external symbol "public: void __cdecl Matrix<int>::print(void)" (?print@?$Matrix@H@@QEAAXXZ) referenced in function main
1>test3.obj : error LNK2019: unresolved external symbol "public: struct Shape __cdecl Matrix<int>::getShape(void)const " (?getShape@?$Matrix@H@@QEBA?AUShape@@XZ) referenced in function main
I'm pulling my hair out here. What am I missing?