From 7d82352a134f1b381c148f3ef14b7970f53e9ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 24 Jul 2021 18:51:19 +0200 Subject: [PATCH] Math: add an ability to construct a Range1D from Math::Vector<1, T>. A Vector<1, T> is implicitly constructible from T but not vice versa (to avoid nasty collisions with builtin operators on scalars) so this is needed. --- src/Magnum/Math/Range.h | 26 +++++++++++++++++++++++--- src/Magnum/Math/Test/RangeTest.cpp | 13 +++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Math/Range.h b/src/Magnum/Math/Range.h index 91c7d21b9..07098b427 100644 --- a/src/Magnum/Math/Range.h +++ b/src/Magnum/Math/Range.h @@ -37,9 +37,24 @@ namespace Magnum { namespace Math { namespace Implementation { template struct RangeTraits; - template struct RangeTraits<1, T> { typedef T Type; }; - template struct RangeTraits<2, T> { typedef Vector2 Type; }; - template struct RangeTraits<3, T> { typedef Vector3 Type; }; + template struct RangeTraits<1, T> { + typedef T Type; + constexpr static Type fromVector(const Vector<1, T>& value) { + return value[0]; + } + }; + template struct RangeTraits<2, T> { + typedef Vector2 Type; + constexpr static Type fromVector(const Vector<2, T>& value) { + return value; + } + }; + template struct RangeTraits<3, T> { + typedef Vector3 Type; + constexpr static Type fromVector(const Vector<3, T>& value) { + return value; + } + }; template struct RangeConverter; } @@ -117,6 +132,11 @@ template class Range { /** @brief Construct a range from minimal and maximal coordinates */ constexpr /*implicit*/ Range(const VectorType& min, const VectorType& max) noexcept: _min{min}, _max{max} {} + /** @overload */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template::type> + #endif + constexpr /*implicit*/ Range(const Vector& min, const Vector& max) noexcept: _min{Implementation::RangeTraits::fromVector(min)}, _max{Implementation::RangeTraits::fromVector(max)} {} /** * @brief Construct a range from a pair of minimal and maximal coordinates diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index 0a712bd47..a073485c9 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -101,6 +101,7 @@ struct RangeTest: Corrade::TestSuite::Tester { explicit RangeTest(); void construct(); + void construct1DFromVectors(); void constructDefault(); void constructNoInit(); void constructFromSize(); @@ -156,6 +157,7 @@ typedef Vector3 Vector3i; RangeTest::RangeTest() { addTests({&RangeTest::construct, + &RangeTest::construct1DFromVectors, &RangeTest::constructDefault, &RangeTest::constructNoInit, &RangeTest::constructFromSize, @@ -211,6 +213,17 @@ void RangeTest::construct() { CORRADE_VERIFY(std::is_nothrow_constructible::value); } +void RangeTest::construct1DFromVectors() { + /* Used by EigenIntegration for Range3D conversion. Implementing the same + there would be a massive verbose pain and this could be useful elsewhere + as well, so implementing that directly on a Range. */ + constexpr Range1Di a = {Vector<1, Int>{3}, Vector<1, Int>{23}}; + + CORRADE_COMPARE(a, (Range<1, Int>(3, 23))); + + CORRADE_VERIFY(std::is_nothrow_constructible, Vector<1, Int>>::value); +} + void RangeTest::constructDefault() { constexpr Range1Di a1; constexpr Range2Di b1;