Skip to content

Instantly share code, notes, and snippets.

@JCBurnside
Last active April 10, 2020 19:54
Show Gist options
  • Save JCBurnside/6be35c6f1f51fe0c2ffa3605780d2e77 to your computer and use it in GitHub Desktop.
Save JCBurnside/6be35c6f1f51fe0c2ffa3605780d2e77 to your computer and use it in GitHub Desktop.
A not so simple implementation of Vector2 in c++ with sample
#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;
}
@JCBurnside
Copy link
Author

Updated to include dot product, scalar multiplication, and norm/length

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment