From 059723049e50bbec0ac463b3e78e51b51d93e09e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 23 Nov 2020 05:38:50 +0700 Subject: [PATCH] union constexpr data --- headers/vmath.hpp/vmath_mat.hpp | 37 +----- headers/vmath.hpp/vmath_vec.hpp | 196 ++++++++++++++++++-------------- untests/vmath_mat_tests.cpp | 68 +---------- untests/vmath_vec_tests.cpp | 116 +++++-------------- 4 files changed, 149 insertions(+), 268 deletions(-) diff --git a/headers/vmath.hpp/vmath_mat.hpp b/headers/vmath.hpp/vmath_mat.hpp index d7acdde..67bf6b6 100644 --- a/headers/vmath.hpp/vmath_mat.hpp +++ b/headers/vmath.hpp/vmath_mat.hpp @@ -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; - using const_reverse_iterator = std::reverse_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"); } diff --git a/headers/vmath.hpp/vmath_vec.hpp b/headers/vmath.hpp/vmath_vec.hpp index 58a9a4f..2f2aafd 100644 --- a/headers/vmath.hpp/vmath_vec.hpp +++ b/headers/vmath.hpp/vmath_vec.hpp @@ -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 { 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& xy) - : data{xy.data[0], xy.data[1]} {} + : x{xy.x}, y{xy.y} {} constexpr explicit vec_base(const vec_base& 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 { 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& 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& yz) - : data{x, yz.data[0], yz.data[1]} {} + : x{x}, y{yz.x}, z{yz.y} {} constexpr explicit vec_base(const vec_base& 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 { 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& 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& 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& 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& xy, const vec_base& 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& 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& 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; - using const_reverse_iterator = std::reverse_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) { 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]; } }; diff --git a/untests/vmath_mat_tests.cpp b/untests/vmath_mat_tests.cpp index 0a4e059..00ce90f 100644 --- a/untests/vmath_mat_tests.cpp +++ b/untests/vmath_mat_tests.cpp @@ -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().size() == 2); - STATIC_REQUIRE(mat().max_size() == 2); - STATIC_REQUIRE_FALSE(mat().empty()); - - STATIC_REQUIRE(mat().size() == 3); - STATIC_REQUIRE(mat().max_size() == 3); - STATIC_REQUIRE_FALSE(mat().empty()); - } - SECTION("operator[]") { { STATIC_REQUIRE(mat2i()[0] == vec2i(1,0)); diff --git a/untests/vmath_vec_tests.cpp b/untests/vmath_vec_tests.cpp index 18534d9..8b0a985 100644 --- a/untests/vmath_vec_tests.cpp +++ b/untests/vmath_vec_tests.cpp @@ -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().size() == 2); - STATIC_REQUIRE(vec().max_size() == 2); - STATIC_REQUIRE_FALSE(vec().empty()); - - STATIC_REQUIRE(vec().size() == 3); - STATIC_REQUIRE(vec().max_size() == 3); - STATIC_REQUIRE_FALSE(vec().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)); } }