Last active
April 10, 2020 19:54
-
-
Save JCBurnside/6be35c6f1f51fe0c2ffa3605780d2e77 to your computer and use it in GitHub Desktop.
A not so simple implementation of Vector2 in c++ with sample
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <type_traits> | |
#include <utility> | |
#include <iostream> | |
#include <math.h> | |
template<typename TLeft, typename TRight> | |
concept Same = std::is_same_v<TLeft,TRight> && std::is_same_v<TRight,TLeft>; | |
template<typename TType> | |
concept Arithmetic = std::is_arithmetic_v<TType>; | |
template<Arithmetic Data> | |
struct Vec2 | |
{ | |
Data x,y; | |
template<typename OtherData> | |
requires requires(const OtherData& od) { x+= od; } | |
Vec2& operator+=(const Vec2<OtherData>& rhs) | |
{ | |
x+=rhs.x; | |
y+=rhs.y; | |
return *this; | |
} | |
template<typename OtherData> | |
requires requires(const OtherData& od) { x -= od; } | |
Vec2& operator-=(const Vec2<OtherData>& rhs) | |
{ | |
x-=rhs.x; | |
y-=rhs.y; | |
return *this; | |
} | |
template<typename TOther> | |
requires requires(const TOther& o) { x *= o } | |
Vec2& operator*=(const TOther& scale) | |
{ | |
x*=scale; | |
y*=scale; | |
return *this; | |
} | |
double Length() const | |
{ | |
return std::sqrt(x * x + y * y); | |
} | |
Vec2<decltype(x/Length())> Normalize() const | |
{ | |
Data l = Length(); | |
return { x/l, y/l }; | |
} | |
}; | |
template<Arithmetic LhsData, Arithmetic RhsData> | |
requires requires(const LhsData& left, const RhsData& right) | |
{ | |
{ left+right } -> Same<LhsData>; | |
} | |
Vec2<LhsData> operator+(const Vec2<LhsData>& lhs, const Vec2<RhsData>& rhs) | |
{ | |
return {lhs.x+rhs.x, lhs.y+rhs.y}; | |
} | |
template<Arithmetic LhsData, Arithmetic RhsData> | |
requires requires(const LhsData& left, const RhsData& right) | |
{ | |
{ left+right } -> Same<RhsData>; | |
} | |
Vec2<RhsData> operator+(const Vec2<LhsData>& lhs, const Vec2<RhsData>& rhs) | |
{ | |
return {lhs.x+rhs.x, lhs.y+rhs.y}; | |
} | |
template<Arithmetic LhsData, Arithmetic RhsData> | |
requires requires(const LhsData& left, const RhsData& right) | |
{ | |
{ left-right } -> Same<LhsData>; | |
} | |
Vec2<LhsData> operator-(const Vec2<LhsData>& lhs, const Vec2<RhsData>& rhs) | |
{ | |
return {lhs.x-rhs.x, lhs.y-rhs.y}; | |
} | |
template<Arithmetic LhsData, Arithmetic RhsData> | |
requires requires(const LhsData& left, const RhsData& right) | |
{ | |
{ left-right } -> Same<RhsData>; | |
} | |
Vec2<RhsData> operator-(const Vec2<LhsData>& lhs, const Vec2<RhsData>& rhs) | |
{ | |
return {lhs.x-rhs.x, lhs.y-rhs.y}; | |
} | |
template<typename Data, typename Scalar> | |
requires requires(const Data& data, const Scalar& scale) | |
{ | |
{ data * scale } -> Same<Data>; | |
} | |
Vec2<Data> operator*(const Vec2<Data>& vec, const Scalar& scale) | |
{ | |
return { vec.x*scale, vec.y*scale }; | |
} | |
template<typename Data, typename Scalar> | |
requires requires(const Data& data, const Scalar& scale) | |
{ | |
{ data * scale } -> Same<Data>; | |
} | |
Vec2<Data> operator*(const Scalar& scale, const Vec2<Data>& vec) | |
{ | |
return { vec.x*scale, vec.y*scale }; | |
} | |
template<typename Data, typename Scalar> | |
requires requires(const Data& data, const Scalar& scale) | |
{ | |
{ data * scale } -> Same<Scalar>; | |
} | |
Vec2<Scalar> operator*(const Vec2<Data>& vec, const Scalar& scale) | |
{ | |
return { vec.x*scale, vec.y*scale }; | |
} | |
template<typename Data, typename Scalar> | |
requires requires(const Data& data, const Scalar& scale) | |
{ | |
{ data * scale } -> Same<Scalar>; | |
} | |
Vec2<Scalar> operator*(const Scalar& scale, const Vec2<Data>& vec) | |
{ | |
return { vec.x*scale, vec.y*scale }; | |
} | |
template<typename TLeftData, typename TRightData> | |
requires requires(const TLeftData& left, const TRightData& right) | |
{ | |
{ left * right } -> Same<TLeftData>; | |
} | |
TLeftData dot(const Vec2<TLeftData>& lhs, const Vec2<TRightData>& rhs) | |
{ | |
return lhs.x * rhs.x + lhs.y * rhs.y; | |
} | |
template<typename TLeftData, typename TRightData> | |
requires requires(const TLeftData& left, const TRightData& right) | |
{ | |
{ left * right } -> Same<TRightData>; | |
} | |
TRightData dot(const Vec2<TLeftData>& lhs, const Vec2<TRightData>& rhs) | |
{ | |
return lhs.x * rhs.x + lhs.y * rhs.y; | |
} | |
template<typename Data> | |
requires requires(const Data& data, std::ostream& os) { os<<data; } | |
std::ostream& operator<<(std::ostream& os, const Vec2<Data>& vec) | |
{ | |
return os << '(' << vec.x << ',' << vec.y << ')'; | |
} | |
int main() | |
{ | |
Vec2<int> vecI{0,0}; | |
Vec2<double> vecD {1.0,-1.5}; | |
Vec2<long> vecL {2L,-2L}; | |
std::cout<< "Int + Double " << vecI + vecD << '\n' | |
<< "Double + Int " << vecD + vecI << '\n' | |
<< "Long + Int " << vecL + vecI << '\n' | |
<< "Int + Long " << vecI + vecL << '\n' | |
<< "Long + Double " << vecL + vecD << '\n' | |
<< "Double + Long " << vecD + vecL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated to include dot product, scalar multiplication, and norm/length