I am writing the following templated vector class.
vectors.h:
#ifndef INCLUDE_HEADERS_VECTORS_H
#define INCLUDE_HEADERS_VECTORS_H
template<class Scalar> class Vector2D;
template<class Scalar> Vector2D<Scalar> operator+(Scalar a, Vector2D<Scalar> v);
template<class Scalar>
class Vector2D {
public:
Vector2D();
Vector2D(Scalar a, Scalar b);
Scalar getX();
Scalar getY();
Vector2D<Scalar> operator+(Scalar a);
friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
private:
Scalar x, y;
};
#endif
vectors.cpp:
#include<headers/vectors.h>
template<class Scalar>
Vector2D<Scalar>::Vector2D() {
x = 0;
y = 0;
}
template<class Scalar>
Vector2D<Scalar>::Vector2D(Scalar a, Scalar b) {
x = a;
y = b;
}
template<class Scalar>
Scalar Vector2D<Scalar>::getX() {
return x;
}
template<class Scalar>
Scalar Vector2D<Scalar>::getY() {
return y;
}
template<class Scalar>
Vector2D<Scalar> Vector2D<Scalar>::operator+(Scalar a) {
return Vector2D<Scalar>(a + x, a + y);
}
template<class Scalar>
Vector2D<Scalar> operator+(Scalar a, Vector2D<Scalar> v) {
return Vector2D<Scalar>(a + v.x, a + v.y);
}
template class Vector2D<float>;
template Vector2D<float> operator+<float>(float a, Vector2D<float> v);
Main.cpp:
#include<headers/vectors.h>
#include<iostream>
int main(int argc, char* argv[]){
Vector2D<float> a(1.0, 3.0);
std::cout<<a.getX()<<" "<<a.getY()<<std::endl;
a = (float)2.0 + a;
std::cout<<a.getX()<<" "<<a.getY()<<std::endl;
a = a + (float)-2.0;
std::cout<<a.getX()<<" "<<a.getY()<<std::endl;
return 0;
}
When I try to compile it with g++ on windows I get the following error:
g++ -Iinclude -Iinclude/SDL2 -Iinclude/headers -Llib -o Main src/*.cpp -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
In file included from src/Main.cpp:2:
include/headers/vectors.h:29:33: error: declaration of 'operator+' as non-function
29 | friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
| ^~~~~~~~
include/headers/vectors.h:29:41: error: expected ';' at end of member declaration
29 | friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
| ^
| ;
include/headers/vectors.h:29:43: error: expected unqualified-id before '<' token
29 | friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
| ^
In file included from src/vectors.cpp:1:
include/headers/vectors.h:29:33: error: declaration of 'operator+' as non-function
29 | friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
| ^~~~~~~~
include/headers/vectors.h:29:41: error: expected ';' at end of member declaration
29 | friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
| ^
| ;
include/headers/vectors.h:29:43: error: expected unqualified-id before '<' token
29 | friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
| ^
src/vectors.cpp:70:18: error: non-class, non-variable partial specialization 'operator+<Scalar>' is not allowed
70 | Vector2D<Scalar> operator+<Scalar>(Scalar a, Vector2D<Scalar> v) {
| ^~~~~~~~~~~~~~~~~
src/vectors.cpp: In instantiation of 'Vector2D<Scalar> operator+(Scalar, Vector2D<Scalar>) [with Scalar = float]':
src/vectors.cpp:96:69: required from here
src/vectors.cpp:71:35: error: 'float Vector2D<float>::x' is private within this context
71 | return Vector2D<Scalar>(a + v.x, a + v.y);
| ~~^
include/headers/vectors.h:37:16: note: declared private here
37 | Scalar x, y;
| ^
src/vectors.cpp:71:44: error: 'float Vector2D<float>::y' is private within this context
71 | return Vector2D<Scalar>(a + v.x, a + v.y);
| ~~^
include/headers/vectors.h:37:19: note: declared private here
37 | Scalar x, y;
| ^
mingw32-make: *** [MakeFile:2: all] Error 1
However, if I change the order of the declarations of the + operator in vectors.h like in the following it will work just fine.
#ifndef INCLUDE_HEADERS_VECTORS_H
#define INCLUDE_HEADERS_VECTORS_H
template<class Scalar> class Vector2D;
template<class Scalar> Vector2D<Scalar> operator+(Scalar a, Vector2D<Scalar> v);
template<class Scalar>
class Vector2D {
public:
Vector2D();
Vector2D(Scalar a, Scalar b);
Scalar getX();
Scalar getY();
friend Vector2D<Scalar> operator+ <>(Scalar a, Vector2D<Scalar> v);
Vector2D<Scalar> operator+(Scalar a);
private:
Scalar x, y;
};
I am completely lost as to why this happens.
I tried to remove the templates and the problem goes away so it must be related.