Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add C++17 structureed binding support (#1320) #1340

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions glm/gtx/structured_bindings.hpp
Original file line number Diff line number Diff line change
@@ -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 <glm/gtx/structured_bindings.hpp> 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 <utility>
#include <cstddef>
namespace std {
template<glm::length_t L,typename T,glm::qualifier Q>
struct tuple_size<glm::vec<L, T, Q>> {
static constexpr size_t value = L;
};
template<glm::length_t C,glm::length_t R, typename T, glm::qualifier Q>
struct tuple_size<glm::mat<C,R, T, Q>> {
static constexpr size_t value = C;
};
template<typename T, glm::qualifier Q>
struct tuple_size<glm::qua<T, Q>> {
static constexpr size_t value = 4;
};
template<std::size_t I,glm::length_t L,typename T,glm::qualifier Q>
struct tuple_element<I, glm::vec<L,T,Q>>
{
GLM_STATIC_ASSERT(I < L,"Index out of bounds");
typedef T type;
};
template<std::size_t I, glm::length_t C, glm::length_t R, typename T, glm::qualifier Q>
struct tuple_element<I, glm::mat<C,R, T, Q>>
{
GLM_STATIC_ASSERT(I < C, "Index out of bounds");
typedef glm::vec<R,T,Q> type;
};
template<std::size_t I, typename T, glm::qualifier Q>
struct tuple_element<I, glm::qua<T, Q>>
{
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<length_t I, length_t L, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR T& get(vec<L, T, Q>& v);
template<length_t I, length_t L, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR T const& get(vec<L, T, Q> const& v);

template<length_t I, length_t C, length_t R, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR vec<R, T, Q>& get(mat<C, R, T, Q>& m);
template<length_t I, length_t C, length_t R, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR vec<R, T, Q> const& get(mat<C, R, T, Q> const& m);

template<length_t I, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR T& get(qua<T, Q>& q);
template<length_t I, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR T const& get(qua<T, Q> const& q);

#if GLM_HAS_RVALUE_REFERENCES
template<length_t I, length_t L,typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR T get(vec<L,T, Q> const&& v);
template<length_t I,length_t C,length_t R, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR vec<R,T,Q> get(mat<C,R,T, Q> const&& m);
template<length_t I, typename T, qualifier Q>
GLM_FUNC_DECL GLM_CONSTEXPR T get(qua<T, Q> const&& q);
#endif
/// @}
}//namespace glm

#include "structured_bindings.inl"
55 changes: 55 additions & 0 deletions glm/gtx/structured_bindings.inl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace glm
{
template<length_t I, length_t L, typename T, qualifier Q>
GLM_CONSTEXPR T& get(vec<L, T, Q>& v) {
GLM_STATIC_ASSERT(I < L, "Index out of bounds");
return v[I];
}
template<length_t I, length_t L, typename T, qualifier Q>
GLM_CONSTEXPR T const& get(vec<L, T, Q> const& v) {
GLM_STATIC_ASSERT(I < L, "Index out of bounds");
return v[I];
}

template<length_t I, length_t C, length_t R, typename T, qualifier Q>
GLM_CONSTEXPR vec<R, T, Q>& get(mat<C, R, T, Q>& m) {
GLM_STATIC_ASSERT(I < C, "Index out of bounds");
return m[I];
}
template<length_t I, length_t C, length_t R, typename T, qualifier Q>
GLM_CONSTEXPR vec<R, T, Q> const& get(mat<C, R, T, Q> const& m) {
GLM_STATIC_ASSERT(I < C, "Index out of bounds");
return m[I];
}

template<length_t I, typename T, qualifier Q>
GLM_CONSTEXPR T& get(qua<T, Q>& q) {
GLM_STATIC_ASSERT(I < 4, "Index out of bounds");
return q[I];
}
template<length_t I, typename T, qualifier Q>
GLM_CONSTEXPR T const& get(qua<T, Q> const& q) {
GLM_STATIC_ASSERT(I < 4, "Index out of bounds");
return q[I];
}

#if GLM_HAS_RVALUE_REFERENCES
template<length_t I, length_t L, typename T, qualifier Q>
GLM_CONSTEXPR T get(vec<L, T, Q> const&& v)
{
GLM_STATIC_ASSERT(I < L, "Index out of bounds");
return v[I];
}
template<length_t I, length_t C, length_t R, typename T, qualifier Q>
GLM_CONSTEXPR vec<R, T, Q> get(mat<C, R, T, Q> const&& m) {
GLM_STATIC_ASSERT(I < C, "Index out of bounds");
return m[I];
}
template<length_t I, typename T, qualifier Q>
GLM_CONSTEXPR T get(qua<T, Q> const&& q) {
GLM_STATIC_ASSERT(I < 4, "Index out of bounds");
return q[I];
}
#endif
}//namespace glm

1 change: 1 addition & 0 deletions test/gtx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading
Loading