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

[Type] Support structured binding for tuple-like types #5208

Merged
merged 3 commits into from
Jan 20, 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
42 changes: 40 additions & 2 deletions Sofa/framework/Type/src/sofa/type/Quat.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class Quat

static Quat identity()
{
return Quat(0,0,0,1);
return Quat(0, 0, 0, 1);
}

void set(Real x, Real y, Real z, Real w)
Expand Down Expand Up @@ -147,7 +147,7 @@ class Quat

void clear()
{
set(0.0,0.0,0.0,1);
set(0, 0, 0, 1);
}

/// Convert the reference frame orientation into an orientation quaternion
Expand Down Expand Up @@ -311,6 +311,30 @@ class Quat
return _q[index];
}

template< std::size_t I >
[[nodiscard]] constexpr Real& get() & noexcept requires (I < 4)
{
return _q[I];
}

template< std::size_t I >
[[nodiscard]] constexpr const Real& get() const& noexcept requires (I < 4)
{
return _q[I];
}

template< std::size_t I >
[[nodiscard]] constexpr Real&& get() && noexcept requires (I < 4)
{
return std::move(_q[I]);
}

template< std::size_t I >
[[nodiscard]] constexpr const Real&& get() const&& noexcept requires (I < 4)
{
return std::move(_q[I]);
}

auto inverse() const -> Quat;

auto quatToRotationVector() const -> Vec3;
Expand Down Expand Up @@ -462,3 +486,17 @@ extern template class SOFA_TYPE_API Quat<float>;
#endif

} // namespace sofa::type

namespace std
{

template<class Real>
struct tuple_size<::sofa::type::Quat<Real> > : integral_constant<size_t, 4> {};

template<std::size_t I, class Real>
struct tuple_element<I, ::sofa::type::Quat<Real> >
{
using type = typename::sofa::type::Quat<Real>::value_type;
};

}
45 changes: 43 additions & 2 deletions Sofa/framework/Type/src/sofa/type/RGBAColor.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <cassert>

#include <sofa/type/fixed_array_algorithms.h>
#include <sofa/type/StrongType.h>


namespace sofa::type
{
Expand All @@ -45,8 +47,9 @@ namespace sofa::type
class SOFA_TYPE_API RGBAColor
{
public:
using value_type = float;
static constexpr sofa::Size NumberOfComponents = 4;
using ComponentArray = std::array<float, NumberOfComponents>;
using ComponentArray = std::array<value_type, NumberOfComponents>;

constexpr RGBAColor()
: m_components{ 1.f, 1.f, 1.f, 1.f } {}
Expand Down Expand Up @@ -132,6 +135,30 @@ class SOFA_TYPE_API RGBAColor
return m_components[i];
}

template< std::size_t I >
[[nodiscard]] constexpr float& get() & noexcept requires (I < 4)
{
return m_components[I];
}

template< std::size_t I >
[[nodiscard]] constexpr const float& get() const& noexcept requires (I < 4)
{
return m_components[I];
}

template< std::size_t I >
[[nodiscard]] constexpr float&& get() && noexcept requires (I < 4)
{
return std::move(m_components[I]);
}

template< std::size_t I >
[[nodiscard]] constexpr const float&& get() const&& noexcept requires (I < 4)
{
return std::move(m_components[I]);
}

void set(float r, float g, float b, float a) ;

bool operator==(const RGBAColor& b) const
Expand Down Expand Up @@ -209,7 +236,6 @@ class SOFA_TYPE_API RGBAColor

static constexpr sofa::Size static_size = NumberOfComponents;
static constexpr sofa::Size size() { return static_size; }
using value_type = float;
using size_type = sofa::Size;

private:
Expand Down Expand Up @@ -285,3 +311,18 @@ constexpr const RGBAColor& RGBAColor::gold() { return g_gold ; }


} // namespace sofa::type


namespace std
{

template<>
struct tuple_size<::sofa::type::RGBAColor > : integral_constant<size_t, ::sofa::type::RGBAColor::NumberOfComponents> {};

template<std::size_t I>
struct tuple_element<I, ::sofa::type::RGBAColor >
{
using type = ::sofa::type::RGBAColor::value_type;
};

}
33 changes: 33 additions & 0 deletions Sofa/framework/Type/src/sofa/type/Vec.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,30 @@ class Vec
return elems[i];
}

template< std::size_t I >
[[nodiscard]] constexpr reference get() & noexcept requires( I < N )
{
return elems[I];
}

template< std::size_t I >
[[nodiscard]] constexpr const_reference get() const& noexcept requires( I < N )
{
return elems[I];
}

template< std::size_t I >
[[nodiscard]] constexpr ValueType&& get() && noexcept requires( I < N )
{
return std::move(elems[I]);
}

template< std::size_t I >
[[nodiscard]] constexpr const ValueType&& get() const&& noexcept requires( I < N )
{
return std::move(elems[I]);
}

// direct access to data
constexpr const ValueType* data() const noexcept
{
Expand Down Expand Up @@ -782,4 +806,13 @@ struct less< sofa::type::Vec<N,T> >
}
};

template<sofa::Size N, class T>
struct tuple_size<::sofa::type::Vec<N,T> > : integral_constant<size_t, N> {};

template<std::size_t I, sofa::Size N, class T >
struct tuple_element<I, ::sofa::type::Vec<N,T> >
{
using type = T;
};

} // namespace std
10 changes: 9 additions & 1 deletion Sofa/framework/Type/test/Quater_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -707,4 +707,12 @@ TEST(QuaterTest, QuaterdFromUnitVectors)
EXPECT_NEAR(0.5894552112230939, quat1[3], errorThreshold);
}


TEST(QuaterTest, StructuredBindings)
{
Quat<double> quat1;
const auto& [a,b,c,d] = quat1;
EXPECT_NEAR(0., a, errorThreshold);
EXPECT_NEAR(0., b, errorThreshold);
EXPECT_NEAR(0., c, errorThreshold);
EXPECT_NEAR(1., d, errorThreshold);
}
15 changes: 15 additions & 0 deletions Sofa/framework/Type/test/RGBAColor_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class Color_Test : public BaseTest,
void checkStreamingOperator(const std::vector<std::string>&) ;
void checkDoubleStreamingOperator(const std::vector<std::string>&) ;
void testEnlight();
void testStructuredBindings();
};

void Color_Test::testEnlight()
Expand All @@ -54,6 +55,15 @@ void Color_Test::testEnlight()
EXPECT_EQ( RGBAColor::lighten(RGBAColor::red(), 0.5), RGBAColor(1.0,0.5,0.5,1.0) ) ;
}

void Color_Test::testStructuredBindings()
{
const auto& [r, g, b, a] = RGBAColor::red();
EXPECT_EQ(r, 1.);
EXPECT_EQ(g, 0.);
EXPECT_EQ(b, 0.);
EXPECT_EQ(a, 1.);
}

void Color_Test::checkCreateFromString()
{
EXPECT_EQ( RGBAColor::fromString("white"), RGBAColor(1.0,1.0,1.0,1.0) ) ;
Expand Down Expand Up @@ -277,6 +287,11 @@ TEST_F(Color_Test, checkEnlight)
this->testEnlight() ;
}

TEST_F(Color_Test, testStructuredBindings)
{
this->testStructuredBindings();
}

std::vector<std::vector<std::string>> testvalues =
{
{" 0 0 0 0","0 0 0 0", "S"},
Expand Down
9 changes: 8 additions & 1 deletion Sofa/framework/Type/test/VecTypes_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,11 @@
#include <sofa/defaulttype/VecTypes.h>
#include <gtest/gtest.h>


TEST(VecTest, StructuredBindings)
{
constexpr sofa::type::Vec3 vec { 1.0, 2.0, 3.0 };
const auto& [a, b, c] = vec;
EXPECT_EQ(a, 1.);
EXPECT_EQ(b, 2.);
EXPECT_EQ(c, 3.);
}
Loading