From 24c1824286e8c2b7c4e3bb481d0b3b8a080f8fc6 Mon Sep 17 00:00:00 2001 From: ZXShady <153229951+ZXShady@users.noreply.github.com> Date: Sun, 10 Nov 2024 10:12:14 +0000 Subject: [PATCH] Add C++17 structureed binding support Add C++17 Structured Bindings support for vec,mat,quat types --- glm/gtx/structured_bindings.hpp | 92 +++++++ glm/gtx/structured_bindings.inl | 55 ++++ test/gtx/CMakeLists.txt | 1 + test/gtx/gtx_structured_bindings.cpp | 366 +++++++++++++++++++++++++++ 4 files changed, 514 insertions(+) create mode 100644 glm/gtx/structured_bindings.hpp create mode 100644 glm/gtx/structured_bindings.inl create mode 100644 test/gtx/gtx_structured_bindings.cpp diff --git a/glm/gtx/structured_bindings.hpp b/glm/gtx/structured_bindings.hpp new file mode 100644 index 00000000..3a7efb2a --- /dev/null +++ b/glm/gtx/structured_bindings.hpp @@ -0,0 +1,92 @@ +/// @ref gtx_structured_bindings +/// @file glm/gtx/structured_bindings.hpp +/// +/// @defgroup gtx_structured_bindings GLM_GTX_structured_bindings +/// @ingroup gtx +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/quaternion.hpp" + +#ifdef __cpp_structured_bindings +#if __cpp_structured_bindings >= 201606L +#include +#include +namespace std { + template + struct tuple_size> { + static constexpr size_t value = L; + }; + template + struct tuple_size> { + static constexpr size_t value = C; + }; + template + struct tuple_size> { + static constexpr size_t value = 4; + }; + template + struct tuple_element> + { + GLM_STATIC_ASSERT(I < L,"Index out of bounds"); + typedef T type; + }; + template + struct tuple_element> + { + GLM_STATIC_ASSERT(I < C, "Index out of bounds"); + typedef glm::vec type; + }; + template + struct tuple_element> + { + GLM_STATIC_ASSERT(I < 4, "Index out of bounds"); + typedef T type; + }; + +} +#endif +#endif + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_iteration is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_io extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_structured_bindings + /// @{ + + template + GLM_FUNC_DECL GLM_CONSTEXPR T& get(vec& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR T const& get(vec const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec& get(mat& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec const& get(mat const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR T& get(qua& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR T const& get(qua const& q); + +#if GLM_HAS_RVALUE_REFERENCES + template + GLM_FUNC_DECL GLM_CONSTEXPR T get(vec const&& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec get(mat const&& m); + template + GLM_FUNC_DECL GLM_CONSTEXPR T get(qua const&& q); +#endif + /// @} +}//namespace glm + +#include "structured_bindings.inl" \ No newline at end of file diff --git a/glm/gtx/structured_bindings.inl b/glm/gtx/structured_bindings.inl new file mode 100644 index 00000000..54d613bd --- /dev/null +++ b/glm/gtx/structured_bindings.inl @@ -0,0 +1,55 @@ +namespace glm +{ + template + GLM_CONSTEXPR T& get(vec& v) { + GLM_STATIC_ASSERT(I < L, "Index out of bounds"); + return v[I]; + } + template + GLM_CONSTEXPR T const& get(vec const& v) { + GLM_STATIC_ASSERT(I < L, "Index out of bounds"); + return v[I]; + } + + template + GLM_CONSTEXPR vec& get(mat& m) { + GLM_STATIC_ASSERT(I < C, "Index out of bounds"); + return m[I]; + } + template + GLM_CONSTEXPR vec const& get(mat const& m) { + GLM_STATIC_ASSERT(I < C, "Index out of bounds"); + return m[I]; + } + + template + GLM_CONSTEXPR T& get(qua& q) { + GLM_STATIC_ASSERT(I < 4, "Index out of bounds"); + return q[I]; + } + template + GLM_CONSTEXPR T const& get(qua const& q) { + GLM_STATIC_ASSERT(I < 4, "Index out of bounds"); + return q[I]; + } + +#if GLM_HAS_RVALUE_REFERENCES + template + GLM_CONSTEXPR T get(vec const&& v) + { + GLM_STATIC_ASSERT(I < L, "Index out of bounds"); + return v[I]; + } + template + GLM_CONSTEXPR vec get(mat const&& m) { + GLM_STATIC_ASSERT(I < C, "Index out of bounds"); + return m[I]; + } + template + GLM_CONSTEXPR T get(qua const&& q) { + GLM_STATIC_ASSERT(I < 4, "Index out of bounds"); + return q[I]; + } +#endif +}//namespace glm + diff --git a/test/gtx/CMakeLists.txt b/test/gtx/CMakeLists.txt index 3a110220..b7686673 100644 --- a/test/gtx/CMakeLists.txt +++ b/test/gtx/CMakeLists.txt @@ -50,6 +50,7 @@ glmCreateTestGTC(gtx_scalar_multiplication) glmCreateTestGTC(gtx_scalar_relational) glmCreateTestGTC(gtx_spline) glmCreateTestGTC(gtx_string_cast) +glmCreateTestGTC(gtx_structured_bindings) glmCreateTestGTC(gtx_texture) glmCreateTestGTC(gtx_type_aligned) glmCreateTestGTC(gtx_type_trait) diff --git a/test/gtx/gtx_structured_bindings.cpp b/test/gtx/gtx_structured_bindings.cpp new file mode 100644 index 00000000..ed4dc24a --- /dev/null +++ b/test/gtx/gtx_structured_bindings.cpp @@ -0,0 +1,366 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +static int test_vec1() { + glm::vec1 v(0); + float& x = glm::get<0>(v); + return (&x != &v.x); +} + +static int test_vec2() { + glm::vec2 v(0); + float& x = glm::get<0>(v); + float& y = glm::get<1>(v); + return (&x != &v.x) + (&y != &v.y); +} + +static int test_vec3() { + glm::vec3 v(0); + float& x = glm::get<0>(v); + float& y = glm::get<1>(v); + float& z = glm::get<2>(v); + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z); +} + +static int test_vec4() { + glm::vec4 v(0); + float& x = glm::get<0>(v); + float& y = glm::get<1>(v); + float& z = glm::get<2>(v); + float& w = glm::get<3>(v); + + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z) + (&w != &v.w); +} + +static int test_const_vec1() { + glm::vec1 const v(0); + float const& x = glm::get<0>(v); + return (&x != &v.x); +} + +static int test_const_vec2() { + glm::vec2 const v(0); + float const& x = glm::get<0>(v); + float const& y = glm::get<1>(v); + return (&x != &v.x) + (&y != &v.y); +} + +static int test_const_vec3() { + glm::vec3 const v(0); + float const& x = glm::get<0>(v); + float const& y = glm::get<1>(v); + float const& z = glm::get<2>(v); + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z); +} + +static int test_const_vec4() { + glm::vec4 const v(0); + float const& x = glm::get<0>(v); + float const& y = glm::get<1>(v); + float const& z = glm::get<2>(v); + float const& w = glm::get<3>(v); + + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z) + (&w != &v.w); +} + + +static int test_quat() { + glm::quat q(0.0f, 0.0f, 0.0f, 0.0f); +#ifdef GLM_FORCE_QUAT_DATA_WXYZ + float& w = glm::get<0>(q); + float& x = glm::get<1>(q); + float& y = glm::get<2>(q); + float& z = glm::get<3>(q); +#else + float& x = glm::get<0>(q); + float& y = glm::get<1>(q); + float& z = glm::get<2>(q); + float& w = glm::get<3>(q); +#endif + return (&x != &q.x) + (&y != &q.y) + (&z != &q.z) + (&w != &q.w); +} + +static int test_const_quat() { + glm::quat const q(0.0f, 0.0f, 0.0f, 0.0f); +#ifdef GLM_FORCE_QUAT_DATA_WXYZ + float const& w = glm::get<0>(q); + float const& x = glm::get<1>(q); + float const& y = glm::get<2>(q); + float const& z = glm::get<3>(q); +#else + float const& x = glm::get<0>(q); + float const& y = glm::get<1>(q); + float const& z = glm::get<2>(q); + float const& w = glm::get<3>(q); +#endif + return (&x != &q.x) + (&y != &q.y) + (&z != &q.z) + (&w != &q.w); +} + + +template +static int test_mat2xR() { + typedef glm::mat<2, R, float> Mat; + Mat m(0); + typename Mat::col_type& c1 = glm::get<0>(m); + typename Mat::col_type& c2 = glm::get<1>(m); + return (&c1 != &m[0]) + (&c2 != &m[1]); +} +template +static int test_const_mat2xR() { + typedef glm::mat<2,R,float> Mat; + Mat const m(0); + typename Mat::col_type const& c1 = glm::get<0>(m); + typename Mat::col_type const& c2 = glm::get<1>(m); + return (&c1 != &m[0]) + (&c2 != &m[1]); +} + +template +static int test_mat3xR() { + typedef glm::mat<3, R, float> Mat; + Mat m(0); + typename Mat::col_type& c1 = glm::get<0>(m); + typename Mat::col_type& c2 = glm::get<1>(m); + typename Mat::col_type& c3 = glm::get<2>(m); + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]); +} + +template +static int test_const_mat3xR() { + typedef glm::mat< 3, R, float> Mat; + Mat const m(0); + typename Mat::col_type const& c1 = glm::get<0>(m); + typename Mat::col_type const& c2 = glm::get<1>(m); + typename Mat::col_type const& c3 = glm::get<2>(m); + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]); +} + +template +static int test_mat4xR() { + typedef glm::mat<4,R,float> Mat; + Mat m(0); + typename Mat::col_type& c1 = glm::get<0>(m); + typename Mat::col_type& c2 = glm::get<1>(m); + typename Mat::col_type& c3 = glm::get<2>(m); + typename Mat::col_type& c4 = glm::get<3>(m); + + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]) + (&c4 != &m[3]); +} + +template +static int test_const_mat4xR() { + typedef glm::mat<4,R,float> Mat; + Mat const m(0); + typename Mat::col_type const& c1 = glm::get<0>(m); + typename Mat::col_type const& c2 = glm::get<1>(m); + typename Mat::col_type const& c3 = glm::get<2>(m); + typename Mat::col_type const& c4 = glm::get<3>(m); + + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]) + (&c4 != &m[3]); +} +#if defined(__cpp_structured_bindings) +#if __cpp_structured_bindings >= 201606L +static int test_structured_vec1() { + glm::vec1 v(0); + auto& [x] = v; + return (&x != &v.x); +} + +static int test_structured_vec2() { + glm::vec2 v(0); + auto& [x, y] = v; + return (&x != &v.x) + (&y != &v.y); +} + +static int test_structured_vec3() { + glm::vec3 v(0); + auto& [x, y, z] = v; + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z); +} + +static int test_structured_vec4() { + glm::vec4 v(0); + auto& [x, y, z, w] = v; + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z) + (&w != &v.w); +} + +static int test_const_structured_vec1() { + glm::vec1 const v(0); + auto const& [x] = v; + return (&x != &v.x); +} + +static int test_const_structured_vec2() { + glm::vec2 const v(0); + auto const& [x, y] = v; + return (&x != &v.x) + (&y != &v.y); +} + +static int test_const_structured_vec3() { + glm::vec3 const v(0); + auto const& [x, y, z] = v; + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z); +} + +static int test_const_structured_vec4() { + glm::vec4 const v(0); + auto const& [x, y, z, w] = v; + return (&x != &v.x) + (&y != &v.y) + (&z != &v.z) + (&w != &v.w); +} + +template +static int test_structured_mat2xR() { + glm::mat<2,R,float,glm::defaultp> m(0); + auto& [c1, c2] = m; + return (&c1 != &m[0]) + (&c2 != &m[1]); +} + +template +static int test_const_structured_mat2xR() { + glm::mat<2, R, float, glm::defaultp> const m(0); + auto const& [c1, c2] = m; + return (&c1 != &m[0]) + (&c2 != &m[1]); +} + +template +static int test_structured_mat3xR() { + glm::mat<3, R, float, glm::defaultp> m(0); + auto& [c1, c2,c3] = m; + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]); +} + +template +static int test_const_structured_mat3xR() { + glm::mat<3, R, float, glm::defaultp> const m(0); + auto const& [c1, c2, c3] = m; + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]); +} + +template +static int test_structured_mat4xR() { + glm::mat<4, R, float, glm::defaultp> m(0); + auto& [c1, c2, c3,c4] = m; + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]) + (&c4 != &m[3]); +} + +template +static int test_const_structured_mat4xR() { + glm::mat<4, R, float, glm::defaultp> const m(0); + auto const& [c1, c2, c3, c4] = m; + return (&c1 != &m[0]) + (&c2 != &m[1]) + (&c3 != &m[2]) + (&c4 != &m[3]); +} + +static int test_structured_quat() { + glm::quat q(0.0f, 0.0f, 0.0f, 0.0f); +#ifdef GLM_FORCE_QUAT_DATA_WXYZ + auto& [w, x, y, z] = q; +#else + auto& [x, y, z, w] = q; +#endif + return (&x != &q.x) + (&y != &q.y) + (&z != &q.z) + (&w != &q.w); +} + +static int test_const_structured_quat() { + glm::quat const q(0.0f, 0.0f, 0.0f, 0.0f); +#ifdef GLM_FORCE_QUAT_DATA_WXYZ + auto const& [w, x, y, z] = q; +#else + auto const& [x, y, z, w] = q; +#endif + return (&x != &q.x) + (&y != &q.y) + (&z != &q.z) + (&w != &q.w); +} + +#endif +#endif +int main() +{ + int Error = 0; + Error += test_vec1(); + Error += test_vec2(); + Error += test_vec3(); + Error += test_vec4(); + + Error += test_const_vec1(); + Error += test_const_vec2(); + Error += test_const_vec3(); + Error += test_const_vec4(); + + + Error += test_quat(); + Error += test_const_quat(); + + + Error += test_mat2xR<2>(); + Error += test_const_mat2xR<2>(); + + Error += test_mat2xR<3>(); + Error += test_const_mat2xR<3>(); + + Error += test_mat2xR<4>(); + Error += test_const_mat2xR<4>(); + + Error += test_mat3xR<2>(); + Error += test_const_mat3xR<2>(); + + Error += test_mat3xR<3>(); + Error += test_const_mat3xR<3>(); + + Error += test_mat3xR<4>(); + Error += test_const_mat3xR<4>(); + + Error += test_mat4xR<2>(); + Error += test_const_mat4xR<2>(); + + Error += test_mat4xR<3>(); + Error += test_const_mat4xR<3>(); + + Error += test_mat4xR<4>(); + Error += test_const_mat4xR<4>(); + +#ifdef __cpp_structured_bindings +#if __cpp_structured_bindings >= 201606L + Error += test_structured_vec1(); + Error += test_structured_vec2(); + Error += test_structured_vec3(); + Error += test_structured_vec4(); + + Error += test_const_structured_vec1(); + Error += test_const_structured_vec2(); + Error += test_const_structured_vec3(); + Error += test_const_structured_vec4(); + + Error += test_structured_quat(); + Error += test_const_structured_quat(); + + Error += test_structured_mat2xR<2>(); + Error += test_const_structured_mat2xR<2>(); + + Error += test_structured_mat2xR<3>(); + Error += test_const_structured_mat2xR<3>(); + + Error += test_structured_mat2xR<4>(); + Error += test_const_structured_mat2xR<4>(); + + Error += test_structured_mat3xR<2>(); + Error += test_const_structured_mat3xR<2>(); + + Error += test_structured_mat3xR<3>(); + Error += test_const_structured_mat3xR<3>(); + + Error += test_structured_mat3xR<4>(); + Error += test_const_structured_mat3xR<4>(); + + Error += test_structured_mat4xR<2>(); + Error += test_const_structured_mat4xR<2>(); + + Error += test_structured_mat4xR<3>(); + Error += test_const_structured_mat4xR<3>(); + + Error += test_structured_mat4xR<4>(); + Error += test_const_structured_mat4xR<4>(); + +#endif +#endif + return Error; +}