I am not very familiar with templates in C++ so I am struggling to solve the following problem.
I have the classes Vector2D
and Vector3D
but I want them to inherit from a class Vector
. To be able to define common functions in Vector
I am using CRTP (Curiously Recurring Template Pattern).
This is a shortend version of my Vector
class:
#pragma once
#include "../stdafx.h"
template <class VectorImpl>
class Vector {
public:
VectorImpl& operator=(const VectorImpl& other);
virtual const float operator*(const VectorImpl& other) const = 0;
friend const VectorImpl operator*(const float& scalar, const VectorImpl& other);
virtual VectorImpl& operator*=(const float& scalar) = 0;
float abs() const;
virtual std::string toString() const = 0;
virtual ~Vector() = 0 {};
protected:
virtual void copyFrom(const VectorImpl& other) = 0;
};
-----------------------------------------------------------------------------------------
#include "Vector.h"
#include "Vector2D.h" // edit
#include "Vector3D.h" // edit
template <class VectorImpl>
VectorImpl& Vector<VectorImpl>::operator=(const VectorImpl& other) {
this->copyFrom(other);
// edit
// return *this;
return static_cast<VectorImpl&>(*this);
}
template <class VectorImpl>
const VectorImpl operator*(const float& scalar, const VectorImpl& other) {
VectorImpl result = other;
result *= scalar;
return result;
}
template <class VectorImpl>
float Vector<VectorImpl>::abs() const {
const VectorImpl thisImpl = static_cast<const VectorImpl&>(*this); // edit
return std::sqrt(thisImpl * thisImpl);
}
// edit
template class Vector<Vector2D>;
template class Vector<Vector3D>;
And this is a shortend version of my Vector2D
class:
#pragma once
#include "../stdafx.h"
#include "Vector.h"
class Vector2D :
public Vector<Vector2D> {
public:
Vector2D();
Vector2D(const Vector2D& other);
Vector2D(const float& xPos, const float& yPos);
const float operator*(const Vector2D& other) const;
Vector2D& operator*=(const float& scalar);
std::string toString() const;
~Vector2D();
protected:
void copyFrom(const Vector2D& other);
private:
float xPos;
float yPos;
};
-----------------------------------------------------------------------------------------
#include "Vector2D.h"
Vector2D::Vector2D() :
xPos(0.0f),
yPos(0.0f) {
}
Vector2D::Vector2D(const Vector2D& other) {
this->copyFrom(other);
}
void Vector2D::copyFrom(const Vector2D& other) {
if (this != &other) {
this->xPos = other.getXPos();
this->yPos = other.getYPos();
}
}
Vector2D::Vector2D(const float& xPos, const float& yPos) {
this->xPos = xPos;
this->yPos = yPos;
}
const float Vector2D::operator*(const Vector2D& other) const {
return this->xPos * other.getXPos() + this->yPos * other.getYPos();
}
Vector2D& Vector2D::operator*=(const float& scalar) {
this->xPos *= scalar;
this->yPos *= scalar;
return *this;
}
std::string Vector2D::toString() const {
std::string ret = std::to_string(this->xPos);
ret += " ";
ret += std::to_string(this->yPos);
return ret;
}
Vector2D::~Vector2D() {
// intentionally left blank
}
The problem is, for every call of a method from Vector2D
(Vector3D
respectively) that is implemented in Vector
I get an LNK2019
error (unresolved external symbol 'symbol' referenced in function 'function').
I am quite sure that I am doing somethin wrong with my template implementation but I can't figure out what it is. I am researching for hours now.
I appreciate any help, so thanks in advance.
EDIT:
I added the necessary instantiations of my template classes but now I get casting errors. Adding
VectorImpl result = static_cast<const VectorImpl>(*this);
or
VectorImpl result = static_cast<VectorImpl>(*this);
doesn't change the problem. What I am I still missing here?
EDIT 2:
Okay of course it hast to be static_cast<const VectorImpl&>(*this)
.
I also added these casts but now I get that damn linking error again. This time only the functions friend operator*
and abs
can't be linked. I don't see much difference to the other functions. So why are they problematic?