363 lines
5.8 KiB
C++
363 lines
5.8 KiB
C++
/**
|
|
* @file dl_array.h
|
|
* @brief 类似std::array,增加xyzw、wh等成员访问
|
|
*
|
|
*
|
|
* @version 1.0
|
|
* @author lveyou
|
|
* @date 26-01-22
|
|
*
|
|
* @note 效率与std::array相当
|
|
* std::array与原生数组不能简单互转
|
|
*/
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <cassert>
|
|
#include <stdexcept>
|
|
#include <type_traits>
|
|
|
|
#if 1
|
|
namespace dl
|
|
{
|
|
//#define DL_ALIGN16
|
|
//#define DL_ALIGN16 alignas(16)
|
|
|
|
//! Array
|
|
template<typename T, size_t N>
|
|
class Array
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
T _data[N];
|
|
Array() = default;
|
|
|
|
constexpr Array(std::initializer_list<T> data)
|
|
{
|
|
size_t i = 0;
|
|
for (auto iter : data)
|
|
{
|
|
_data[i] = iter;
|
|
++i;
|
|
if (i >= N)
|
|
return;
|
|
}
|
|
for (; i < N; ++i)
|
|
_data[i] = {};
|
|
}
|
|
constexpr T& operator[](size_t i)
|
|
{
|
|
assert(i < N);
|
|
return _data[i];
|
|
}
|
|
constexpr const T& operator[](size_t i) const
|
|
{
|
|
assert(i < N);
|
|
return _data[i];
|
|
}
|
|
constexpr T& at(size_t i)
|
|
{
|
|
if (i >= N)
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
return _data[i];
|
|
}
|
|
constexpr const T& at(size_t i) const
|
|
{
|
|
if (i >= N)
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
return _data[i];
|
|
}
|
|
|
|
T* begin() { return &_data[0]; }
|
|
T* end() { return &_data[N]; }
|
|
const T* begin() const { return &_data[0]; }
|
|
const T* end() const { return &_data[N]; }
|
|
bool empty() const { return false; }
|
|
};
|
|
|
|
template<typename T>
|
|
requires std::is_trivial_v<T>
|
|
class Array<T, 2>
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
T x;
|
|
T y;
|
|
};
|
|
struct
|
|
{
|
|
T w;
|
|
T h;
|
|
};
|
|
struct
|
|
{
|
|
T col;
|
|
T row;
|
|
};
|
|
T _data[2];
|
|
};
|
|
Array() = default;
|
|
|
|
constexpr Array(std::initializer_list<T> data)
|
|
{
|
|
size_t N_LIST = std::size(data);
|
|
for (size_t i = 0; i < 2; ++i)
|
|
_data[i] = i < N_LIST ? *(data.begin() + i) : T{};
|
|
}
|
|
constexpr const T& Get(size_t i) const
|
|
{
|
|
assert(i < 2);
|
|
return _data[i];
|
|
}
|
|
constexpr T& operator[](size_t i)
|
|
{
|
|
assert(i < 2);
|
|
return _data[i];
|
|
}
|
|
constexpr const T& operator[](size_t i) const
|
|
{
|
|
assert(i < 2);
|
|
return _data[i];
|
|
}
|
|
constexpr T& at(size_t i)
|
|
{
|
|
assert(i < 2);
|
|
if (i < 2)
|
|
return _data[i];
|
|
else
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
constexpr const T& at(size_t i) const
|
|
{
|
|
assert(i < 2);
|
|
if (i < 2)
|
|
return _data[i];
|
|
else
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
|
|
T* begin() { return &x; }
|
|
T* end() { return &x + 2; }
|
|
const T* begin() const { return &x; }
|
|
const T* end() const { return &x + 2; }
|
|
bool empty() const { return false; }
|
|
};
|
|
|
|
template<typename T>
|
|
requires std::is_trivial_v<T>
|
|
class Array<T, 3>
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
T x;
|
|
T y;
|
|
T z;
|
|
};
|
|
struct
|
|
{
|
|
T col;
|
|
T row;
|
|
T dep;
|
|
};
|
|
T _data[3];
|
|
};
|
|
Array() = default;
|
|
|
|
constexpr Array(std::initializer_list<T> data)
|
|
{
|
|
size_t N_LIST = std::size(data);
|
|
for (size_t i = 0; i < 3; ++i)
|
|
_data[i] = i < N_LIST ? *(data.begin() + i) : T{};
|
|
}
|
|
constexpr const T& Get(size_t i) const
|
|
{
|
|
assert(i < 3);
|
|
return _data[i];
|
|
}
|
|
constexpr T& operator[](size_t i)
|
|
{
|
|
assert(i < 3);
|
|
return _data[i];
|
|
}
|
|
constexpr const T& operator[](size_t i) const
|
|
{
|
|
assert(i < 3);
|
|
return _data[i];
|
|
}
|
|
constexpr T& at(size_t i)
|
|
{
|
|
assert(i < 3);
|
|
if (i < 3)
|
|
return _data[i];
|
|
else
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
constexpr const T& at(size_t i) const
|
|
{
|
|
assert(i < 3);
|
|
if (i < 3)
|
|
return _data[i];
|
|
else
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
|
|
T* begin() { return &x; }
|
|
T* end() { return &x + 3; }
|
|
const T* begin() const { return &x; }
|
|
const T* end() const { return &x + 3; }
|
|
bool empty() const { return false; }
|
|
};
|
|
|
|
template<typename T>
|
|
requires std::is_trivial_v<T>
|
|
class Array<T, 4>
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
T x;
|
|
T y;
|
|
T z;
|
|
T w;
|
|
};
|
|
struct
|
|
{
|
|
T lt;
|
|
T rt;
|
|
T rb;
|
|
T lb;
|
|
};
|
|
struct
|
|
{
|
|
T r;
|
|
T g;
|
|
T b;
|
|
T a;
|
|
};
|
|
struct
|
|
{
|
|
T left;
|
|
T top;
|
|
T right;
|
|
T bottom;
|
|
};
|
|
T _data[4];
|
|
};
|
|
Array() = default;
|
|
|
|
constexpr Array(std::initializer_list<T> data)
|
|
{
|
|
size_t N_LIST = std::size(data);
|
|
for (size_t i = 0; i < 4; ++i)
|
|
_data[i] = i < N_LIST ? *(data.begin() + i) : T{};
|
|
}
|
|
constexpr const T& Get(size_t i) const
|
|
{
|
|
assert(i < 4);
|
|
return _data[i];
|
|
}
|
|
constexpr T Sum(size_t i, size_t j) const
|
|
{
|
|
assert(i < 4);
|
|
assert(j < 4);
|
|
return _data[i] + _data[j];
|
|
}
|
|
constexpr T& operator[](size_t i)
|
|
{
|
|
assert(i < 4);
|
|
return _data[i];
|
|
}
|
|
constexpr const T& operator[](size_t i) const
|
|
{
|
|
assert(i < 4);
|
|
return _data[i];
|
|
}
|
|
constexpr T& at(size_t i)
|
|
{
|
|
assert(i < 4);
|
|
if (i < 4)
|
|
return _data[i];
|
|
else
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
constexpr const T& at(size_t i) const
|
|
{
|
|
assert(i < 4);
|
|
if (i < 4)
|
|
return _data[i];
|
|
else
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
|
|
T* begin() { return &x; }
|
|
T* end() { return &x + 4; }
|
|
const T* begin() const { return &x; }
|
|
const T* end() const { return &x + 4; }
|
|
bool empty() const { return false; }
|
|
};
|
|
|
|
template<typename T>
|
|
class Array<T, 0>
|
|
{
|
|
public:
|
|
using value_type = T;
|
|
T _data[1];
|
|
Array() = default;
|
|
|
|
constexpr Array(std::initializer_list<T> data)
|
|
{
|
|
}
|
|
constexpr T& operator[](size_t i)
|
|
{
|
|
return *begin();
|
|
}
|
|
constexpr const T& operator[](size_t i) const
|
|
{
|
|
return *begin();
|
|
}
|
|
constexpr T& at(size_t i)
|
|
{
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
constexpr const T& at(size_t i) const
|
|
{
|
|
throw std::out_of_range("dl::Array::at outrange");
|
|
}
|
|
|
|
T* begin() { return nullptr; }
|
|
T* end() { return nullptr; }
|
|
const T* begin() const { return nullptr; }
|
|
const T* end() const { return nullptr; }
|
|
bool empty() const { return true; }
|
|
};
|
|
|
|
template<typename T, size_t N>
|
|
constexpr bool operator==(const Array<T, N>& a, const Array<T, N>& b)
|
|
{
|
|
for (size_t i = 0; i < N; ++i)
|
|
{
|
|
if (a[i] != b[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
}
|
|
#else
|
|
template<typename T, size_t N>
|
|
using Array = std::array<T, N>;
|
|
#endif
|
|
|