Mark some common constructors and other stuff as constexpr

This commit is contained in:
sfan5 2024-03-09 22:05:06 +01:00
parent 1e89db1b80
commit a7dd075dec
11 changed files with 113 additions and 122 deletions

View File

@ -43,15 +43,15 @@ const char* const sBuiltInVertexTypeNames[] =
struct S3DVertex
{
//! default constructor
S3DVertex() : Color(0xffffffff) {}
constexpr S3DVertex() : Color(0xffffffff) {}
//! constructor
S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
constexpr S3DVertex(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
: Pos(x,y,z), Normal(nx,ny,nz), Color(c), TCoords(tu,tv) {}
//! constructor
S3DVertex(const core::vector3df& pos, const core::vector3df& normal,
SColor color, const core::vector2d<f32>& tcoords)
constexpr S3DVertex(const core::vector3df& pos, const core::vector3df& normal,
SColor color, const core::vector2df& tcoords)
: Pos(pos), Normal(normal), Color(color), TCoords(tcoords) {}
//! Position
@ -64,21 +64,21 @@ struct S3DVertex
SColor Color;
//! Texture coordinates
core::vector2d<f32> TCoords;
core::vector2df TCoords;
bool operator==(const S3DVertex& other) const
constexpr bool operator==(const S3DVertex& other) const
{
return ((Pos == other.Pos) && (Normal == other.Normal) &&
(Color == other.Color) && (TCoords == other.TCoords));
}
bool operator!=(const S3DVertex& other) const
constexpr bool operator!=(const S3DVertex& other) const
{
return ((Pos != other.Pos) || (Normal != other.Normal) ||
(Color != other.Color) || (TCoords != other.TCoords));
}
bool operator<(const S3DVertex& other) const
constexpr bool operator<(const S3DVertex& other) const
{
return ((Pos < other.Pos) ||
((Pos == other.Pos) && (Normal < other.Normal)) ||
@ -111,56 +111,58 @@ or other special materials.
struct S3DVertex2TCoords : public S3DVertex
{
//! default constructor
S3DVertex2TCoords() : S3DVertex() {}
constexpr S3DVertex2TCoords() : S3DVertex() {}
//! constructor with two different texture coords, but no normal
S3DVertex2TCoords(f32 x, f32 y, f32 z, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2)
constexpr S3DVertex2TCoords(f32 x, f32 y, f32 z, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2)
: S3DVertex(x,y,z, 0.0f, 0.0f, 0.0f, c, tu,tv), TCoords2(tu2,tv2) {}
//! constructor with two different texture coords, but no normal
S3DVertex2TCoords(const core::vector3df& pos, SColor color,
const core::vector2d<f32>& tcoords, const core::vector2d<f32>& tcoords2)
constexpr S3DVertex2TCoords(const core::vector3df& pos, SColor color,
const core::vector2df& tcoords, const core::vector2df& tcoords2)
: S3DVertex(pos, core::vector3df(), color, tcoords), TCoords2(tcoords2) {}
//! constructor with all values
S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, const SColor& color,
const core::vector2d<f32>& tcoords, const core::vector2d<f32>& tcoords2)
constexpr S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal, const SColor& color,
const core::vector2df& tcoords, const core::vector2df& tcoords2)
: S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords2) {}
//! constructor with all values
S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2)
constexpr S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz,
SColor c, f32 tu, f32 tv, f32 tu2, f32 tv2)
: S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), TCoords2(tu2,tv2) {}
//! constructor with the same texture coords and normal
S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
constexpr S3DVertex2TCoords(f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz,
SColor c, f32 tu, f32 tv)
: S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), TCoords2(tu,tv) {}
//! constructor with the same texture coords and normal
S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal,
SColor color, const core::vector2d<f32>& tcoords)
constexpr S3DVertex2TCoords(const core::vector3df& pos, const core::vector3df& normal,
SColor color, const core::vector2df& tcoords)
: S3DVertex(pos, normal, color, tcoords), TCoords2(tcoords) {}
//! constructor from S3DVertex
S3DVertex2TCoords(const S3DVertex& o) : S3DVertex(o) {}
constexpr S3DVertex2TCoords(const S3DVertex& o) : S3DVertex(o) {}
//! Second set of texture coordinates
core::vector2d<f32> TCoords2;
core::vector2df TCoords2;
//! Equality operator
bool operator==(const S3DVertex2TCoords& other) const
constexpr bool operator==(const S3DVertex2TCoords& other) const
{
return ((static_cast<S3DVertex>(*this)==static_cast<const S3DVertex&>(other)) &&
(TCoords2 == other.TCoords2));
}
//! Inequality operator
bool operator!=(const S3DVertex2TCoords& other) const
constexpr bool operator!=(const S3DVertex2TCoords& other) const
{
return ((static_cast<S3DVertex>(*this)!=static_cast<const S3DVertex&>(other)) ||
(TCoords2 != other.TCoords2));
}
bool operator<(const S3DVertex2TCoords& other) const
constexpr bool operator<(const S3DVertex2TCoords& other) const
{
return ((static_cast<S3DVertex>(*this) < other) ||
((static_cast<S3DVertex>(*this) == static_cast<const S3DVertex&>(other)) && (TCoords2 < other.TCoords2)));
@ -194,19 +196,19 @@ struct S3DVertexTangents : public S3DVertex
S3DVertexTangents() : S3DVertex() { }
//! constructor
S3DVertexTangents(f32 x, f32 y, f32 z, f32 nx=0.0f, f32 ny=0.0f, f32 nz=0.0f,
constexpr S3DVertexTangents(f32 x, f32 y, f32 z, f32 nx=0.0f, f32 ny=0.0f, f32 nz=0.0f,
SColor c = 0xFFFFFFFF, f32 tu=0.0f, f32 tv=0.0f,
f32 tanx=0.0f, f32 tany=0.0f, f32 tanz=0.0f,
f32 bx=0.0f, f32 by=0.0f, f32 bz=0.0f)
: S3DVertex(x,y,z, nx,ny,nz, c, tu,tv), Tangent(tanx,tany,tanz), Binormal(bx,by,bz) { }
//! constructor
S3DVertexTangents(const core::vector3df& pos, SColor c,
constexpr S3DVertexTangents(const core::vector3df& pos, SColor c,
const core::vector2df& tcoords)
: S3DVertex(pos, core::vector3df(), c, tcoords) { }
//! constructor
S3DVertexTangents(const core::vector3df& pos,
constexpr S3DVertexTangents(const core::vector3df& pos,
const core::vector3df& normal, SColor c,
const core::vector2df& tcoords,
const core::vector3df& tangent=core::vector3df(),
@ -214,7 +216,7 @@ struct S3DVertexTangents : public S3DVertex
: S3DVertex(pos, normal, c, tcoords), Tangent(tangent), Binormal(binormal) { }
//! constructor from S3DVertex
S3DVertexTangents(const S3DVertex& o) : S3DVertex(o) {}
constexpr S3DVertexTangents(const S3DVertex& o) : S3DVertex(o) {}
//! Tangent vector along the x-axis of the texture
core::vector3df Tangent;
@ -222,21 +224,21 @@ struct S3DVertexTangents : public S3DVertex
//! Binormal vector (tangent x normal)
core::vector3df Binormal;
bool operator==(const S3DVertexTangents& other) const
constexpr bool operator==(const S3DVertexTangents& other) const
{
return ((static_cast<S3DVertex>(*this)==static_cast<const S3DVertex&>(other)) &&
(Tangent == other.Tangent) &&
(Binormal == other.Binormal));
}
bool operator!=(const S3DVertexTangents& other) const
constexpr bool operator!=(const S3DVertexTangents& other) const
{
return ((static_cast<S3DVertex>(*this)!=static_cast<const S3DVertex&>(other)) ||
(Tangent != other.Tangent) ||
(Binormal != other.Binormal));
}
bool operator<(const S3DVertexTangents& other) const
constexpr bool operator<(const S3DVertexTangents& other) const
{
return ((static_cast<S3DVertex>(*this) < other) ||
((static_cast<S3DVertex>(*this) == static_cast<const S3DVertex&>(other)) && (Tangent < other.Tangent)) ||

View File

@ -264,11 +264,11 @@ namespace video
//! Constructs the color from 4 values representing the alpha, red, green and blue component.
/** Must be values between 0 and 255. */
SColor (u32 a, u32 r, u32 g, u32 b)
constexpr SColor (u32 a, u32 r, u32 g, u32 b)
: color(((a & 0xff)<<24) | ((r & 0xff)<<16) | ((g & 0xff)<<8) | (b & 0xff)) {}
//! Constructs the color from a 32 bit value. Could be another color.
SColor(u32 clr)
constexpr SColor(u32 clr)
: color(clr) {}
//! Returns the alpha component of the color.
@ -648,7 +648,7 @@ namespace video
class SColorHSL
{
public:
SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
constexpr SColorHSL ( f32 h = 0.f, f32 s = 0.f, f32 l = 0.f )
: Hue ( h ), Saturation ( s ), Luminance ( l ) {}
void fromRGB(const SColorf &color);

View File

@ -22,23 +22,26 @@ class aabbox3d
public:
//! Default Constructor.
aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {}
constexpr aabbox3d(): MinEdge(-1,-1,-1), MaxEdge(1,1,1) {}
//! Constructor with min edge and max edge.
aabbox3d(const vector3d<T>& min, const vector3d<T>& max): MinEdge(min), MaxEdge(max) {}
constexpr aabbox3d(const vector3d<T>& min, const vector3d<T>& max): MinEdge(min), MaxEdge(max) {}
//! Constructor with only one point.
aabbox3d(const vector3d<T>& init): MinEdge(init), MaxEdge(init) {}
constexpr aabbox3d(const vector3d<T>& init): MinEdge(init), MaxEdge(init) {}
//! Constructor with min edge and max edge as single values, not vectors.
aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz): MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {}
constexpr aabbox3d(T minx, T miny, T minz, T maxx, T maxy, T maxz):
MinEdge(minx, miny, minz), MaxEdge(maxx, maxy, maxz) {}
// operators
//! Equality operator
/** \param other box to compare with.
\return True if both boxes are equal, else false. */
inline bool operator==(const aabbox3d<T>& other) const { return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);}
constexpr inline bool operator==(const aabbox3d<T>& other) const
{ return (MinEdge == other.MinEdge && other.MaxEdge == MaxEdge); }
//! Inequality operator
/** \param other box to compare with.
\return True if both boxes are different, else false. */
inline bool operator!=(const aabbox3d<T>& other) const { return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge);}
constexpr inline bool operator!=(const aabbox3d<T>& other) const
{ return !(MinEdge == other.MinEdge && other.MaxEdge == MaxEdge); }
// functions

View File

@ -20,16 +20,16 @@ namespace core
{
public:
//! Default constructor for empty dimension
dimension2d() : Width(0), Height(0) {}
constexpr dimension2d() : Width(0), Height(0) {}
//! Constructor with width and height
dimension2d(const T& width, const T& height)
constexpr dimension2d(const T& width, const T& height)
: Width(width), Height(height) {}
dimension2d(const vector2d<T>& other); // Defined in vector2d.h
//! Use this constructor only where you are sure that the conversion is valid.
template <class U>
explicit dimension2d(const dimension2d<U>& other) :
explicit constexpr dimension2d(const dimension2d<U>& other) :
Width((T)other.Width), Height((T)other.Height) { }
template <class U>

View File

@ -18,11 +18,11 @@ class line2d
{
public:
//! Default constructor for line going from (0,0) to (1,1).
line2d() : start(0,0), end(1,1) {}
constexpr line2d() : start(0,0), end(1,1) {}
//! Constructor for line between the two points.
line2d(T xa, T ya, T xb, T yb) : start(xa, ya), end(xb, yb) {}
constexpr line2d(T xa, T ya, T xb, T yb) : start(xa, ya), end(xb, yb) {}
//! Constructor for line between the two points given as vectors.
line2d(const vector2d<T>& start, const vector2d<T>& end) : start(start), end(end) {}
constexpr line2d(const vector2d<T>& start, const vector2d<T>& end) : start(start), end(end) {}
// operators
@ -32,9 +32,9 @@ class line2d
line2d<T> operator-(const vector2d<T>& point) const { return line2d<T>(start - point, end - point); }
line2d<T>& operator-=(const vector2d<T>& point) { start -= point; end -= point; return *this; }
bool operator==(const line2d<T>& other) const
constexpr bool operator==(const line2d<T>& other) const
{ return (start==other.start && end==other.end) || (end==other.start && start==other.end);}
bool operator!=(const line2d<T>& other) const
constexpr bool operator!=(const line2d<T>& other) const
{ return !(start==other.start && end==other.end) || (end==other.start && start==other.end);}
// functions

View File

@ -20,11 +20,11 @@ class line3d
//! Default constructor
/** line from (0,0,0) to (1,1,1) */
line3d() : start(0,0,0), end(1,1,1) {}
constexpr line3d() : start(0,0,0), end(1,1,1) {}
//! Constructor with two points
line3d(T xa, T ya, T za, T xb, T yb, T zb) : start(xa, ya, za), end(xb, yb, zb) {}
constexpr line3d(T xa, T ya, T za, T xb, T yb, T zb) : start(xa, ya, za), end(xb, yb, zb) {}
//! Constructor with two points as vectors
line3d(const vector3d<T>& start, const vector3d<T>& end) : start(start), end(end) {}
constexpr line3d(const vector3d<T>& start, const vector3d<T>& end) : start(start), end(end) {}
// operators
@ -34,9 +34,9 @@ class line3d
line3d<T> operator-(const vector3d<T>& point) const { return line3d<T>(start - point, end - point); }
line3d<T>& operator-=(const vector3d<T>& point) { start -= point; end -= point; return *this; }
bool operator==(const line3d<T>& other) const
constexpr bool operator==(const line3d<T>& other) const
{ return (start==other.start && end==other.end) || (end==other.start && start==other.end);}
bool operator!=(const line3d<T>& other) const
constexpr bool operator!=(const line3d<T>& other) const
{ return !(start==other.start && end==other.end) || (end==other.start && start==other.end);}
// functions

View File

@ -62,7 +62,7 @@ namespace core
CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
//! Constructor with value initialization
CMatrix4(const T& r0c0, const T& r0c1, const T& r0c2, const T& r0c3,
constexpr CMatrix4(const T& r0c0, const T& r0c1, const T& r0c2, const T& r0c3,
const T& r1c0, const T& r1c1, const T& r1c2, const T& r1c3,
const T& r2c0, const T& r2c1, const T& r2c2, const T& r2c3,
const T& r3c0, const T& r3c1, const T& r3c2, const T& r3c3)
@ -119,10 +119,24 @@ namespace core
}
//! Returns true if other matrix is equal to this matrix.
bool operator==(const CMatrix4<T> &other) const;
constexpr bool operator==(const CMatrix4<T> &other) const
{
#if defined ( USE_MATRIX_TEST )
if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
return true;
#endif
for (s32 i = 0; i < 16; ++i)
if (M[i] != other.M[i])
return false;
return true;
}
//! Returns true if other matrix is not equal to this matrix.
bool operator!=(const CMatrix4<T> &other) const;
constexpr bool operator!=(const CMatrix4<T> &other) const
{
return !(*this == other);
}
//! Add another matrix.
CMatrix4<T> operator+(const CMatrix4<T>& other) const;
@ -1510,28 +1524,6 @@ namespace core
}
template <class T>
inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
{
#if defined ( USE_MATRIX_TEST )
if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
return true;
#endif
for (s32 i = 0; i < 16; ++i)
if (M[i] != other.M[i])
return false;
return true;
}
template <class T>
inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
{
return !(*this == other);
}
// Builds a right-handed perspective projection matrix based on a field of view
template <class T>
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(

View File

@ -32,10 +32,10 @@ class quaternion
public:
//! Default Constructor
quaternion() : X(0.0f), Y(0.0f), Z(0.0f), W(1.0f) {}
constexpr quaternion() : X(0.0f), Y(0.0f), Z(0.0f), W(1.0f) {}
//! Constructor
quaternion(f32 x, f32 y, f32 z, f32 w) : X(x), Y(y), Z(z), W(w) { }
constexpr quaternion(f32 x, f32 y, f32 z, f32 w) : X(x), Y(y), Z(z), W(w) { }
//! Constructor which converts Euler angles (radians) to a quaternion
quaternion(f32 x, f32 y, f32 z);
@ -49,10 +49,19 @@ class quaternion
#endif
//! Equality operator
bool operator==(const quaternion& other) const;
constexpr bool operator==(const quaternion& other) const
{
return ((X == other.X) &&
(Y == other.Y) &&
(Z == other.Z) &&
(W == other.W));
}
//! inequality operator
bool operator!=(const quaternion& other) const;
constexpr bool operator!=(const quaternion& other) const
{
return !(*this == other);
}
#ifndef IRR_TEST_BROKEN_QUATERNION_USE
//! Matrix assignment operator
@ -221,21 +230,6 @@ inline quaternion::quaternion(const matrix4& mat)
}
#endif
// equal operator
inline bool quaternion::operator==(const quaternion& other) const
{
return ((X == other.X) &&
(Y == other.Y) &&
(Z == other.Z) &&
(W == other.W));
}
// inequality operator
inline bool quaternion::operator!=(const quaternion& other) const
{
return !(*this == other);
}
#ifndef IRR_TEST_BROKEN_QUATERNION_USE
// matrix assignment operator
inline quaternion& quaternion::operator=(const matrix4& m)

View File

@ -27,24 +27,24 @@ namespace core
public:
//! Default constructor creating empty rectangle at (0,0)
rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {}
constexpr rect() : UpperLeftCorner(0,0), LowerRightCorner(0,0) {}
//! Constructor with two corners
rect(T x, T y, T x2, T y2)
constexpr rect(T x, T y, T x2, T y2)
: UpperLeftCorner(x,y), LowerRightCorner(x2,y2) {}
//! Constructor with two corners
rect(const position2d<T>& upperLeft, const position2d<T>& lowerRight)
constexpr rect(const position2d<T>& upperLeft, const position2d<T>& lowerRight)
: UpperLeftCorner(upperLeft), LowerRightCorner(lowerRight) {}
//! Constructor with upper left corner and dimension
template <class U>
rect(const position2d<T>& pos, const dimension2d<U>& size)
constexpr rect(const position2d<T>& pos, const dimension2d<U>& size)
: UpperLeftCorner(pos), LowerRightCorner(pos.X + size.Width, pos.Y + size.Height) {}
//! Constructor with upper left at 0,0 and lower right using dimension
template <class U>
explicit rect(const dimension2d<U>& size)
explicit constexpr rect(const dimension2d<U>& size)
: UpperLeftCorner(0,0), LowerRightCorner(size.Width, size.Height) {}
//! move right by given numbers
@ -78,14 +78,14 @@ namespace core
}
//! equality operator
bool operator==(const rect<T>& other) const
constexpr bool operator==(const rect<T>& other) const
{
return (UpperLeftCorner == other.UpperLeftCorner &&
LowerRightCorner == other.LowerRightCorner);
}
//! inequality operator
bool operator!=(const rect<T>& other) const
constexpr bool operator!=(const rect<T>& other) const
{
return (UpperLeftCorner != other.UpperLeftCorner ||
LowerRightCorner != other.LowerRightCorner);

View File

@ -23,13 +23,13 @@ class vector2d
{
public:
//! Default constructor (null vector)
vector2d() : X(0), Y(0) {}
constexpr vector2d() : X(0), Y(0) {}
//! Constructor with two different values
vector2d(T nx, T ny) : X(nx), Y(ny) {}
constexpr vector2d(T nx, T ny) : X(nx), Y(ny) {}
//! Constructor with the same value for both members
explicit vector2d(T n) : X(n), Y(n) {}
explicit constexpr vector2d(T n) : X(n), Y(n) {}
vector2d(const dimension2d<T>& other) : X(other.Width), Y(other.Height) {}
constexpr vector2d(const dimension2d<T>& other) : X(other.Width), Y(other.Height) {}
// operators
@ -76,34 +76,34 @@ public:
}
//! sort in order X, Y.
bool operator<=(const vector2d<T>&other) const
constexpr bool operator<=(const vector2d<T>&other) const
{
return !(*this > other);
}
//! sort in order X, Y.
bool operator>=(const vector2d<T>&other) const
constexpr bool operator>=(const vector2d<T>&other) const
{
return !(*this < other);
}
//! sort in order X, Y.
bool operator<(const vector2d<T>&other) const
constexpr bool operator<(const vector2d<T>&other) const
{
return X < other.X || (X == other.X && Y < other.Y);
}
//! sort in order X, Y.
bool operator>(const vector2d<T>&other) const
constexpr bool operator>(const vector2d<T>&other) const
{
return X > other.X || (X == other.X && Y > other.Y);
}
bool operator==(const vector2d<T>& other) const {
constexpr bool operator==(const vector2d<T>& other) const {
return X == other.X && Y == other.Y;
}
bool operator!=(const vector2d<T>& other) const {
constexpr bool operator!=(const vector2d<T>& other) const {
return !(*this == other);
}

View File

@ -24,11 +24,11 @@ namespace core
{
public:
//! Default constructor (null vector).
vector3d() : X(0), Y(0), Z(0) {}
constexpr vector3d() : X(0), Y(0), Z(0) {}
//! Constructor with three different values
vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {}
constexpr vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {}
//! Constructor with the same value for all elements
explicit vector3d(T n) : X(n), Y(n), Z(n) {}
explicit constexpr vector3d(T n) : X(n), Y(n), Z(n) {}
// operators
@ -69,37 +69,37 @@ namespace core
}
//! sort in order X, Y, Z.
bool operator<=(const vector3d<T>&other) const
constexpr bool operator<=(const vector3d<T>&other) const
{
return !(*this > other);
}
//! sort in order X, Y, Z.
bool operator>=(const vector3d<T>&other) const
constexpr bool operator>=(const vector3d<T>&other) const
{
return !(*this < other);
}
//! sort in order X, Y, Z.
bool operator<(const vector3d<T>&other) const
constexpr bool operator<(const vector3d<T>&other) const
{
return X < other.X || (X == other.X && Y < other.Y) ||
(X == other.X && Y == other.Y && Z < other.Z);
}
//! sort in order X, Y, Z.
bool operator>(const vector3d<T>&other) const
constexpr bool operator>(const vector3d<T>&other) const
{
return X > other.X || (X == other.X && Y > other.Y) ||
(X == other.X && Y == other.Y && Z > other.Z);
}
bool operator==(const vector3d<T>& other) const
constexpr bool operator==(const vector3d<T>& other) const
{
return X == other.X && Y == other.Y && Z == other.Z;
}
bool operator!=(const vector3d<T>& other) const
constexpr bool operator!=(const vector3d<T>& other) const
{
return !(*this == other);
}