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 reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using iterator = value_type*; static constexpr std::size_t size = Size;
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;
public: public:
using base_type::rows; using base_type::rows;
using base_type::mat_base; using base_type::mat_base;
@@ -199,42 +192,22 @@ namespace vmath_hpp
} }
} }
constexpr iterator begin() noexcept { return iterator(rows); } constexpr reference operator[](std::size_t index) noexcept {
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 {
return rows[index]; 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]; return rows[index];
} }
constexpr reference at(size_type index) { constexpr reference at(std::size_t index) {
if ( index >= Size ) { if ( index >= Size ) {
throw std::out_of_range("mat::at"); throw std::out_of_range("mat::at");
} }
return rows[index]; return rows[index];
} }
constexpr const_reference at(size_type index) const { constexpr const_reference at(std::size_t index) const {
if ( index >= Size ) { if ( index >= Size ) {
throw std::out_of_range("mat::at"); throw std::out_of_range("mat::at");
} }

View File

@@ -8,6 +8,18 @@
#include "vmath_fwd.hpp" #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 namespace vmath_hpp::detail
{ {
template < typename T, std::size_t Size > template < typename T, std::size_t Size >
@@ -16,106 +28,153 @@ namespace vmath_hpp::detail
template < typename T > template < typename T >
class vec_base<T, 2> { class vec_base<T, 2> {
public: public:
T data[2]{}; union {
struct { T x, y; };
T data[2];
};
public: public:
vec_base() = default; constexpr vec_base()
: x{0}, y{0} {}
constexpr explicit vec_base(T v) constexpr explicit vec_base(T v)
: data{v, v} {} : x{v}, y{v} {}
constexpr vec_base(T x, T y) constexpr vec_base(T x, T y)
: data{x, y} {} : x{x}, y{y} {}
constexpr explicit vec_base(const vec_base<T, 3>& xy) 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) 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 T& operator[](std::size_t index) noexcept {
constexpr const T& x() const noexcept { return data[0]; } switch ( index ) {
default:
case 0: return x;
case 1: return y;
}
}
constexpr T& y() noexcept { return data[1]; } constexpr const T& operator[](std::size_t index) const noexcept {
constexpr const T& y() const noexcept { return data[1]; } switch ( index ) {
default:
case 0: return x;
case 1: return y;
}
}
}; };
template < typename T > template < typename T >
class vec_base<T, 3> { class vec_base<T, 3> {
public: public:
T data[3]{}; union {
struct { T x, y, z; };
T data[3];
};
public: public:
vec_base() = default; constexpr vec_base()
: x{0}, y{0}, z{0} {}
constexpr explicit vec_base(T v) 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) 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) 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) 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) 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 T& operator[](std::size_t index) noexcept {
constexpr const T& x() const noexcept { return data[0]; } 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& operator[](std::size_t index) const noexcept {
constexpr const T& y() const noexcept { return data[1]; } switch ( index ) {
default:
constexpr T& z() noexcept { return data[2]; } case 0: return x;
constexpr const T& z() const noexcept { return data[2]; } case 1: return y;
case 2: return z;
}
}
}; };
template < typename T > template < typename T >
class vec_base<T, 4> { class vec_base<T, 4> {
public: public:
T data[4]{}; union {
struct { T x, y, z, w; };
T data[4];
};
public: public:
vec_base() = default; constexpr vec_base()
: x{0}, y{0}, z{0}, w{0} {}
constexpr explicit vec_base(T v) 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) 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) 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) 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) 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) 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) 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) 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 T& operator[](std::size_t index) noexcept {
constexpr const T& x() const noexcept { return data[0]; } 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& operator[](std::size_t index) const noexcept {
constexpr const T& y() const noexcept { return data[1]; } switch ( index ) {
default:
constexpr T& z() noexcept { return data[2]; } case 0: return x;
constexpr const T& z() const noexcept { return data[2]; } case 1: return y;
case 2: return z;
constexpr T& w() noexcept { return data[3]; } case 3: return w;
constexpr const T& w() const noexcept { return data[3]; } }
}
}; };
} }
#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 namespace vmath_hpp
{ {
template < typename T, std::size_t Size > template < typename T, std::size_t Size >
@@ -132,17 +191,10 @@ namespace vmath_hpp
using reference = value_type&; using reference = value_type&;
using const_reference = const value_type&; using const_reference = const value_type&;
using iterator = value_type*; static constexpr std::size_t size = Size;
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;
public: public:
using base_type::data;
using base_type::vec_base; using base_type::vec_base;
using base_type::operator[];
vec() = default; vec() = default;
@@ -155,50 +207,22 @@ namespace vmath_hpp
void swap(vec& other) noexcept(std::is_nothrow_swappable_v<T>) { void swap(vec& other) noexcept(std::is_nothrow_swappable_v<T>) {
for ( std::size_t i = 0; i < Size; ++i ) { for ( std::size_t i = 0; i < Size; ++i ) {
using std::swap; using std::swap;
swap(data[i], other.data[i]); swap((*this)[i], other[i]);
} }
} }
constexpr iterator begin() noexcept { return iterator(data); } constexpr reference at(std::size_t index) {
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) {
if ( index >= Size ) { if ( index >= Size ) {
throw std::out_of_range("vec::at"); 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 ) { if ( index >= Size ) {
throw std::out_of_range("vec::at"); throw std::out_of_range("vec::at");
} }
return data[index]; return (*this)[index];
} }
}; };

View File

@@ -16,7 +16,11 @@ namespace
TEST_CASE("vmath/mat") { TEST_CASE("vmath/mat") {
using namespace vmath_hpp; 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(mat2i{}) == sizeof(int) * 2 * 2);
STATIC_REQUIRE(sizeof(mat3i{}) == sizeof(int) * 3 * 3); STATIC_REQUIRE(sizeof(mat3i{}) == sizeof(int) * 3 * 3);
STATIC_REQUIRE(sizeof(mat4i{}) == sizeof(int) * 4 * 4); 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[]") { SECTION("operator[]") {
{ {
STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); STATIC_REQUIRE(mat2i()[0] == vec2i(1,0));

View File

@@ -16,7 +16,11 @@ namespace
TEST_CASE("vmath/vec") { TEST_CASE("vmath/vec") {
using namespace vmath_hpp; 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(vec2i{}) == sizeof(int) * 2);
STATIC_REQUIRE(sizeof(vec3i{}) == sizeof(int) * 3); STATIC_REQUIRE(sizeof(vec3i{}) == sizeof(int) * 3);
STATIC_REQUIRE(sizeof(vec4i{}) == sizeof(int) * 4); STATIC_REQUIRE(sizeof(vec4i{}) == sizeof(int) * 4);
@@ -24,14 +28,14 @@ TEST_CASE("vmath/vec") {
SECTION("ctors") { SECTION("ctors") {
{ {
STATIC_REQUIRE(vec2i().x() == 0); STATIC_REQUIRE(vec2i().x == 0);
STATIC_REQUIRE(vec2i().y() == 0); STATIC_REQUIRE(vec2i().y == 0);
STATIC_REQUIRE(vec2i(1).x() == 1); STATIC_REQUIRE(vec2i(1).x == 1);
STATIC_REQUIRE(vec2i(1).y() == 1); STATIC_REQUIRE(vec2i(1).y == 1);
STATIC_REQUIRE(vec2i(1,2).x() == 1); STATIC_REQUIRE(vec2i(1,2).x == 1);
STATIC_REQUIRE(vec2i(1,2).y() == 2); STATIC_REQUIRE(vec2i(1,2).y == 2);
} }
{ {
constexpr vec2i v(1,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[]") { SECTION("operator[]") {
{ {
STATIC_REQUIRE(vec2i(1,2).x() == 1); STATIC_REQUIRE(vec2i(1,2).x == 1);
STATIC_REQUIRE(vec2i(1,2).y() == 2); STATIC_REQUIRE(vec2i(1,2).y == 2);
STATIC_REQUIRE(vec3i(1,2,3).x() == 1); STATIC_REQUIRE(vec3i(1,2,3).x == 1);
STATIC_REQUIRE(vec3i(1,2,3).y() == 2); STATIC_REQUIRE(vec3i(1,2,3).y == 2);
STATIC_REQUIRE(vec3i(1,2,3).z() == 3); STATIC_REQUIRE(vec3i(1,2,3).z == 3);
STATIC_REQUIRE(vec4i(1,2,3,4).x() == 1); 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).y == 2);
STATIC_REQUIRE(vec4i(1,2,3,4).z() == 3); 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).w == 4);
} }
{ {
STATIC_REQUIRE(vec2i(1,2)[0] == 1); STATIC_REQUIRE(vec2i(1,2)[0] == 1);
@@ -182,23 +124,23 @@ TEST_CASE("vmath/vec") {
} }
{ {
vec2i v; vec2i v;
v.x() = 1; v.x = 1;
v.y() = 2; v.y = 2;
REQUIRE(v == vec2i(1,2)); REQUIRE(v == vec2i(1,2));
} }
{ {
vec3i v; vec3i v;
v.x() = 1; v.x = 1;
v.y() = 2; v.y = 2;
v.z() = 3; v.z = 3;
REQUIRE(v == vec3i(1,2,3)); REQUIRE(v == vec3i(1,2,3));
} }
{ {
vec4i v; vec4i v;
v.x() = 1; v.x = 1;
v.y() = 2; v.y = 2;
v.z() = 3; v.z = 3;
v.w() = 4; v.w = 4;
REQUIRE(v == vec4i(1,2,3,4)); REQUIRE(v == vec4i(1,2,3,4));
} }
} }