Files
2026-08-29 23:04:26 +08:00

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