union constexpr data

This commit is contained in:
BlackMATov
2020-11-23 05:38:50 +07:00
parent 2cee3a4d42
commit 059723049e
4 changed files with 149 additions and 268 deletions

View File

@@ -172,14 +172,7 @@ namespace vmath_hpp
using reference = value_type&;
using const_reference = const value_type&;
using iterator = value_type*;
using const_iterator = const value_type*;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
static constexpr std::size_t size = Size;
public:
using base_type::rows;
using base_type::mat_base;
@@ -199,42 +192,22 @@ namespace vmath_hpp
}
}
constexpr iterator begin() noexcept { return iterator(rows); }
constexpr const_iterator begin() const noexcept { return const_iterator(rows); }
constexpr const_iterator cbegin() const noexcept { return const_iterator(rows); }
constexpr iterator end() noexcept { return iterator(rows + Size); }
constexpr const_iterator end() const noexcept { return const_iterator(rows + Size); }
constexpr const_iterator cend() const noexcept { return const_iterator(rows + Size); }
constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
constexpr size_type size() const noexcept { return Size; }
constexpr size_type max_size() const noexcept { return Size; }
constexpr bool empty() const noexcept { return !Size; }
constexpr reference operator[](size_type index) noexcept {
constexpr reference operator[](std::size_t index) noexcept {
return rows[index];
}
constexpr const_reference operator[](size_type index) const noexcept {
constexpr const_reference operator[](std::size_t index) const noexcept {
return rows[index];
}
constexpr reference at(size_type index) {
constexpr reference at(std::size_t index) {
if ( index >= Size ) {
throw std::out_of_range("mat::at");
}
return rows[index];
}
constexpr const_reference at(size_type index) const {
constexpr const_reference at(std::size_t index) const {
if ( index >= Size ) {
throw std::out_of_range("mat::at");
}

View File

@@ -8,6 +8,18 @@
#include "vmath_fwd.hpp"
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpedantic"
#elif defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
# pragma clang diagnostic ignored "-Wnested-anon-types"
#elif defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4201)
#endif
namespace vmath_hpp::detail
{
template < typename T, std::size_t Size >
@@ -16,106 +28,153 @@ namespace vmath_hpp::detail
template < typename T >
class vec_base<T, 2> {
public:
T data[2]{};
union {
struct { T x, y; };
T data[2];
};
public:
vec_base() = default;
constexpr vec_base()
: x{0}, y{0} {}
constexpr explicit vec_base(T v)
: data{v, v} {}
: x{v}, y{v} {}
constexpr vec_base(T x, T y)
: data{x, y} {}
: x{x}, y{y} {}
constexpr explicit vec_base(const vec_base<T, 3>& xy)
: data{xy.data[0], xy.data[1]} {}
: x{xy.x}, y{xy.y} {}
constexpr explicit vec_base(const vec_base<T, 4>& xy)
: data{xy.data[0], xy.data[1]} {}
: x{xy.x}, y{xy.y} {}
constexpr T& x() noexcept { return data[0]; }
constexpr const T& x() const noexcept { return data[0]; }
constexpr T& operator[](std::size_t index) noexcept {
switch ( index ) {
default:
case 0: return x;
case 1: return y;
}
}
constexpr T& y() noexcept { return data[1]; }
constexpr const T& y() const noexcept { return data[1]; }
constexpr const T& operator[](std::size_t index) const noexcept {
switch ( index ) {
default:
case 0: return x;
case 1: return y;
}
}
};
template < typename T >
class vec_base<T, 3> {
public:
T data[3]{};
union {
struct { T x, y, z; };
T data[3];
};
public:
vec_base() = default;
constexpr vec_base()
: x{0}, y{0}, z{0} {}
constexpr explicit vec_base(T v)
: data{v, v, v} {}
: x{v}, y{v}, z{v} {}
constexpr vec_base(T x, T y, T z)
: data{x, y, z} {}
: x{x}, y{y}, z{z} {}
constexpr vec_base(const vec_base<T, 2>& xy, T z)
: data{xy.data[0], xy.data[1], z} {}
: x{xy.x}, y{xy.y}, z{z} {}
constexpr vec_base(T x, const vec_base<T, 2>& yz)
: data{x, yz.data[0], yz.data[1]} {}
: x{x}, y{yz.x}, z{yz.y} {}
constexpr explicit vec_base(const vec_base<T, 4>& xyz)
: data{xyz.data[0], xyz.data[1], xyz.data[2]} {}
: x{xyz.x}, y{xyz.y}, z{xyz.z} {}
constexpr T& x() noexcept { return data[0]; }
constexpr const T& x() const noexcept { return data[0]; }
constexpr T& operator[](std::size_t index) noexcept {
switch ( index ) {
default:
case 0: return x;
case 1: return y;
case 2: return z;
}
}
constexpr T& y() noexcept { return data[1]; }
constexpr const T& y() const noexcept { return data[1]; }
constexpr T& z() noexcept { return data[2]; }
constexpr const T& z() const noexcept { return data[2]; }
constexpr const T& operator[](std::size_t index) const noexcept {
switch ( index ) {
default:
case 0: return x;
case 1: return y;
case 2: return z;
}
}
};
template < typename T >
class vec_base<T, 4> {
public:
T data[4]{};
union {
struct { T x, y, z, w; };
T data[4];
};
public:
vec_base() = default;
constexpr vec_base()
: x{0}, y{0}, z{0}, w{0} {}
constexpr explicit vec_base(T v)
: data{v, v, v, v} {}
: x{v}, y{v}, z{v}, w{v} {}
constexpr vec_base(T x, T y, T z, T w)
: data{x, y, z, w} {}
: x{x}, y{y}, z{z}, w{w} {}
constexpr vec_base(const vec_base<T, 2>& xy, T z, T w)
: data{xy.data[0], xy.data[1], z, w} {}
: x{xy.x}, y{xy.y}, z{z}, w{w} {}
constexpr vec_base(T x, const vec_base<T, 2>& yz, T w)
: data{x, yz.data[0], yz.data[1], w} {}
: x{x}, y{yz.x}, z{yz.y}, w{w} {}
constexpr vec_base(T x, T y, const vec_base<T, 2>& zw)
: data{x, y, zw.data[0], zw.data[1]} {}
: x{x}, y{y}, z{zw.x}, w{zw.y} {}
constexpr vec_base(const vec_base<T, 2>& xy, const vec_base<T, 2>& zw)
: data{xy.data[0], xy.data[1], zw.data[0], zw.data[1]} {}
: x{xy.x}, y{xy.y}, z{zw.x}, w{zw.y} {}
constexpr vec_base(const vec_base<T, 3>& xyz, T w)
: data{xyz.data[0], xyz.data[1], xyz.data[2], w} {}
: x{xyz.x}, y{xyz.y}, z{xyz.z}, w{w} {}
constexpr vec_base(T x, const vec_base<T, 3>& yzw)
: data{x, yzw.data[0], yzw.data[1], yzw.data[2]} {}
: x{x}, y{yzw.x}, z{yzw.y}, w{yzw.z} {}
constexpr T& x() noexcept { return data[0]; }
constexpr const T& x() const noexcept { return data[0]; }
constexpr T& operator[](std::size_t index) noexcept {
switch ( index ) {
default:
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
constexpr T& y() noexcept { return data[1]; }
constexpr const T& y() const noexcept { return data[1]; }
constexpr T& z() noexcept { return data[2]; }
constexpr const T& z() const noexcept { return data[2]; }
constexpr T& w() noexcept { return data[3]; }
constexpr const T& w() const noexcept { return data[3]; }
constexpr const T& operator[](std::size_t index) const noexcept {
switch ( index ) {
default:
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
};
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#elif defined(__clang__)
# pragma clang diagnostic pop
#elif defined(_MSC_VER)
# pragma warning(pop)
#endif
namespace vmath_hpp
{
template < typename T, std::size_t Size >
@@ -132,17 +191,10 @@ namespace vmath_hpp
using reference = value_type&;
using const_reference = const value_type&;
using iterator = value_type*;
using const_iterator = const value_type*;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
static constexpr std::size_t size = Size;
public:
using base_type::data;
using base_type::vec_base;
using base_type::operator[];
vec() = default;
@@ -155,50 +207,22 @@ namespace vmath_hpp
void swap(vec& other) noexcept(std::is_nothrow_swappable_v<T>) {
for ( std::size_t i = 0; i < Size; ++i ) {
using std::swap;
swap(data[i], other.data[i]);
swap((*this)[i], other[i]);
}
}
constexpr iterator begin() noexcept { return iterator(data); }
constexpr const_iterator begin() const noexcept { return const_iterator(data); }
constexpr const_iterator cbegin() const noexcept { return const_iterator(data); }
constexpr iterator end() noexcept { return iterator(data + Size); }
constexpr const_iterator end() const noexcept { return const_iterator(data + Size); }
constexpr const_iterator cend() const noexcept { return const_iterator(data + Size); }
constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
constexpr size_type size() const noexcept { return Size; }
constexpr size_type max_size() const noexcept { return Size; }
constexpr bool empty() const noexcept { return !Size; }
constexpr reference operator[](size_type index) noexcept {
return data[index];
}
constexpr const_reference operator[](size_type index) const noexcept {
return data[index];
}
constexpr reference at(size_type index) {
constexpr reference at(std::size_t index) {
if ( index >= Size ) {
throw std::out_of_range("vec::at");
}
return data[index];
return (*this)[index];
}
constexpr const_reference at(size_type index) const {
constexpr const_reference at(std::size_t index) const {
if ( index >= Size ) {
throw std::out_of_range("vec::at");
}
return data[index];
return (*this)[index];
}
};

View File

@@ -16,7 +16,11 @@ namespace
TEST_CASE("vmath/mat") {
using namespace vmath_hpp;
SECTION("sizeof") {
SECTION("size/sizeof") {
STATIC_REQUIRE(mat2i{}.size == 2);
STATIC_REQUIRE(mat3i{}.size == 3);
STATIC_REQUIRE(mat4i{}.size == 4);
STATIC_REQUIRE(sizeof(mat2i{}) == sizeof(int) * 2 * 2);
STATIC_REQUIRE(sizeof(mat3i{}) == sizeof(int) * 3 * 3);
STATIC_REQUIRE(sizeof(mat4i{}) == sizeof(int) * 4 * 4);
@@ -102,68 +106,6 @@ TEST_CASE("vmath/mat") {
}
}
SECTION("iter") {
{
mat2i v{1,2,3,4};
mat2i::iterator i = v.begin();
REQUIRE(*i++ == vec2i{1,2});
REQUIRE(*i++ == vec2i{3,4});
REQUIRE(v.end() == i);
}
{
const mat2i v{1,2,3,4};
mat2i::const_iterator i = v.begin();
REQUIRE(*i++ == vec2i{1,2});
REQUIRE(*i++ == vec2i{3,4});
REQUIRE(v.end() == i);
}
{
mat2i v{1,2,3,4};
for ( auto i = v.begin(); i < v.end(); ++i ) {
*i = vec2i(i->x() * 2, i->y() * 2);
}
REQUIRE(v == mat2i(2,4,6,8));
}
}
SECTION("riter") {
{
mat2i v{1,2,3,4};
mat2i::reverse_iterator i = v.rbegin();
REQUIRE(*i++ == vec2i{3,4});
REQUIRE(*i++ == vec2i{1,2});
REQUIRE(v.rend() == i);
for ( auto j = v.rbegin(); j < v.rend(); ++j ) {
*j = vec2i(j->x() * 2, j->y() * 2);
}
REQUIRE(v == mat2i(2,4,6,8));
}
{
const mat2i v{1,2,3,4};
mat2i::const_reverse_iterator i = v.rbegin();
REQUIRE(*i++ == vec2i{3,4});
REQUIRE(*i++ == vec2i{1,2});
REQUIRE(v.rend() == i);
}
{
mat2i v{1,2,3,4};
for ( auto i = v.rbegin(); i < v.rend(); ++i ) {
*i = vec2i(i->x() * 2, i->y() * 2);
}
REQUIRE(v == mat2i(2,4,6,8));
}
}
SECTION("size/max_size/empty") {
STATIC_REQUIRE(mat<int, 2>().size() == 2);
STATIC_REQUIRE(mat<int, 2>().max_size() == 2);
STATIC_REQUIRE_FALSE(mat<int, 2>().empty());
STATIC_REQUIRE(mat<int, 3>().size() == 3);
STATIC_REQUIRE(mat<int, 3>().max_size() == 3);
STATIC_REQUIRE_FALSE(mat<int, 3>().empty());
}
SECTION("operator[]") {
{
STATIC_REQUIRE(mat2i()[0] == vec2i(1,0));

View File

@@ -16,7 +16,11 @@ namespace
TEST_CASE("vmath/vec") {
using namespace vmath_hpp;
SECTION("sizeof") {
SECTION("size/sizeof") {
STATIC_REQUIRE(vec2i{}.size == 2);
STATIC_REQUIRE(vec3i{}.size == 3);
STATIC_REQUIRE(vec4i{}.size == 4);
STATIC_REQUIRE(sizeof(vec2i{}) == sizeof(int) * 2);
STATIC_REQUIRE(sizeof(vec3i{}) == sizeof(int) * 3);
STATIC_REQUIRE(sizeof(vec4i{}) == sizeof(int) * 4);
@@ -24,14 +28,14 @@ TEST_CASE("vmath/vec") {
SECTION("ctors") {
{
STATIC_REQUIRE(vec2i().x() == 0);
STATIC_REQUIRE(vec2i().y() == 0);
STATIC_REQUIRE(vec2i().x == 0);
STATIC_REQUIRE(vec2i().y == 0);
STATIC_REQUIRE(vec2i(1).x() == 1);
STATIC_REQUIRE(vec2i(1).y() == 1);
STATIC_REQUIRE(vec2i(1).x == 1);
STATIC_REQUIRE(vec2i(1).y == 1);
STATIC_REQUIRE(vec2i(1,2).x() == 1);
STATIC_REQUIRE(vec2i(1,2).y() == 2);
STATIC_REQUIRE(vec2i(1,2).x == 1);
STATIC_REQUIRE(vec2i(1,2).y == 2);
}
{
constexpr vec2i v(1,2);
@@ -100,81 +104,19 @@ TEST_CASE("vmath/vec") {
}
}
SECTION("iter") {
{
vec2i v(1,2);
vec2i::iterator i = v.begin();
REQUIRE(*i++ == 1);
REQUIRE(*i++ == 2);
REQUIRE(v.end() == i);
}
{
const vec2i v(1,2);
vec2i::const_iterator i = v.begin();
REQUIRE(*i++ == 1);
REQUIRE(*i++ == 2);
REQUIRE(v.end() == i);
}
{
vec2i v(1,2);
for ( auto i = v.begin(); i < v.end(); ++i ) {
*i = *i * 2;
}
REQUIRE(v == vec2i(2,4));
}
}
SECTION("riter") {
{
vec2i v(1,2);
vec2i::reverse_iterator i = v.rbegin();
REQUIRE(*i++ == 2);
REQUIRE(*i++ == 1);
REQUIRE(v.rend() == i);
for ( auto j = v.rbegin(); j < v.rend(); ++j ) {
*j = *j * 2;
}
REQUIRE(v == vec2i(2,4));
}
{
const vec2i v(1,2);
vec2i::const_reverse_iterator i = v.rbegin();
REQUIRE(*i++ == 2);
REQUIRE(*i++ == 1);
REQUIRE(v.rend() == i);
}
{
vec2i v(1,2);
for ( auto i = v.rbegin(); i < v.rend(); ++i ) {
*i = *i * 2;
}
REQUIRE(v == vec2i(2,4));
}
}
SECTION("size/max_size/empty") {
STATIC_REQUIRE(vec<int, 2>().size() == 2);
STATIC_REQUIRE(vec<int, 2>().max_size() == 2);
STATIC_REQUIRE_FALSE(vec<int, 2>().empty());
STATIC_REQUIRE(vec<int, 3>().size() == 3);
STATIC_REQUIRE(vec<int, 3>().max_size() == 3);
STATIC_REQUIRE_FALSE(vec<int, 3>().empty());
}
SECTION("operator[]") {
{
STATIC_REQUIRE(vec2i(1,2).x() == 1);
STATIC_REQUIRE(vec2i(1,2).y() == 2);
STATIC_REQUIRE(vec2i(1,2).x == 1);
STATIC_REQUIRE(vec2i(1,2).y == 2);
STATIC_REQUIRE(vec3i(1,2,3).x() == 1);
STATIC_REQUIRE(vec3i(1,2,3).y() == 2);
STATIC_REQUIRE(vec3i(1,2,3).z() == 3);
STATIC_REQUIRE(vec3i(1,2,3).x == 1);
STATIC_REQUIRE(vec3i(1,2,3).y == 2);
STATIC_REQUIRE(vec3i(1,2,3).z == 3);
STATIC_REQUIRE(vec4i(1,2,3,4).x() == 1);
STATIC_REQUIRE(vec4i(1,2,3,4).y() == 2);
STATIC_REQUIRE(vec4i(1,2,3,4).z() == 3);
STATIC_REQUIRE(vec4i(1,2,3,4).w() == 4);
STATIC_REQUIRE(vec4i(1,2,3,4).x == 1);
STATIC_REQUIRE(vec4i(1,2,3,4).y == 2);
STATIC_REQUIRE(vec4i(1,2,3,4).z == 3);
STATIC_REQUIRE(vec4i(1,2,3,4).w == 4);
}
{
STATIC_REQUIRE(vec2i(1,2)[0] == 1);
@@ -182,23 +124,23 @@ TEST_CASE("vmath/vec") {
}
{
vec2i v;
v.x() = 1;
v.y() = 2;
v.x = 1;
v.y = 2;
REQUIRE(v == vec2i(1,2));
}
{
vec3i v;
v.x() = 1;
v.y() = 2;
v.z() = 3;
v.x = 1;
v.y = 2;
v.z = 3;
REQUIRE(v == vec3i(1,2,3));
}
{
vec4i v;
v.x() = 1;
v.y() = 2;
v.z() = 3;
v.w() = 4;
v.x = 1;
v.y = 2;
v.z = 3;
v.w = 4;
REQUIRE(v == vec4i(1,2,3,4));
}
}