diff --git a/doc/changelog.dox b/doc/changelog.dox index 63c66d743..18845eb04 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -385,6 +385,15 @@ See also: matrices, and with the default on @ref Math::RectangularMatrix being zero-fill while @ref Math::Matrix stays with the identity for consistency with other constructors. +- @ref Math::Bezier::data(), @ref Math::BoolVector::data(), + @ref Math::Complex::data(), @ref Math::CubicHermite::data(), + @ref Math::Dual::data(), @ref Math::DualComplex::data(), + @ref Math::DualQuaternion::data(), @ref Math::Frustum::data(), + @ref Math::Quaternion::data(), @ref Math::Range::data(), + @ref Math::RectangularMatrix::data() and @ref Math::Vector::data() now + return a reference to a fixed-size array instead of a pointer (i.e., + @cpp T(&)[size] @ce instead of @cpp T* @ce) for more convenient usage in + APIs that take sized views. @subsubsection changelog-latest-changes-meshtools MeshTools library @@ -946,6 +955,13 @@ See also: process. Existing code that calls these with unsanitized inputs now additionally needs to account for reflection as suggested in the documentation. +- @ref Math::Complex::data(), @ref Math::CubicHermite::data(), + @ref Math::Dual::data(), @ref Math::DualComplex::data(), + @ref Math::DualQuaternion::data(), @ref Math::Frustum::data(), + @ref Math::Quaternion::data(), @ref Math::Range::data() and + @ref Math::RectangularMatrix::data() are no longer @cpp constexpr @ce in + order to make them return a reference to a fixed-size array instead of a + pointer, which was deemed a more useful property. - @ref SceneGraph::Object::addChild() no longer requires the type constructor to have the last parameter a parent object object pointer, as that was quite limiting. Instead it's calling @ref SceneGraph::Object::setParent() diff --git a/src/Magnum/Math/Bezier.h b/src/Magnum/Math/Bezier.h index 2ed92f673..f2760997b 100644 --- a/src/Magnum/Math/Bezier.h +++ b/src/Magnum/Math/Bezier.h @@ -137,12 +137,21 @@ template class Bezier { /** * @brief Raw data - * @return One-dimensional array of @cpp order + 1 @ce elements * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of @cpp order + 1 @ce elements, + * i.e. @cpp T(&)[size] @ce. * @see @ref operator[]() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - Vector* data() { return _data; } - constexpr const Vector* data() const { return _data; } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + Vector* data(); + constexpr const Vector* data() const; /**< @overload */ + #else + auto data() -> Vector(&)[order + 1] { return _data; } + constexpr auto data() const -> const Vector(&)[order + 1] { return _data; } + #endif /** @brief Equality comparison */ bool operator==(const Bezier& other) const { diff --git a/src/Magnum/Math/BoolVector.h b/src/Magnum/Math/BoolVector.h index 8badcbf7c..c9842d6fd 100644 --- a/src/Magnum/Math/BoolVector.h +++ b/src/Magnum/Math/BoolVector.h @@ -130,12 +130,21 @@ template class BoolVector { /** * @brief Raw data - * @return Array of DataSize length * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of @ref DataSize elements, i.e. + * @cpp UnsignedByte(&)[DataSize] @ce. * @see @ref operator[](), @ref set() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - UnsignedByte* data() { return _data; } - constexpr const UnsignedByte* data() const { return _data; } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + UnsignedByte* data(); + constexpr const UnsignedByte* data() const; /**< @overload */ + #else + auto data() -> UnsignedByte(&)[DataSize] { return _data; } + constexpr auto data() const -> const UnsignedByte(&)[DataSize] { return _data; } + #endif /** @brief Bit at given position */ constexpr bool operator[](std::size_t i) const { diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index 415315a2d..382186861 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -183,12 +183,30 @@ template class Complex { /** * @brief Raw data - * @return One-dimensional array of two elements * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of two elements, i.e. + * @cpp T(&)[2] @ce. * @see @ref real(), @ref imaginary() - */ - T* data() { return &_real; } - constexpr const T* data() const { return &_real; } /**< @overload */ + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[2] { + return reinterpret_cast(_real); + } + /* Can't be constexpr anymore, the only other solution would be to + store `T _data[2]` instead of the two variables, but that may make + the internal implementation too error prone. Similarly as with + RectangularMatrix::data(), having a statically sized array returned + is a far more useful property than constexpr, so that wins. */ + auto data() const -> const T(&)[2] { + return reinterpret_cast(_real); + } + #endif /** @brief Equality comparison */ bool operator==(const Complex& other) const { diff --git a/src/Magnum/Math/CubicHermite.h b/src/Magnum/Math/CubicHermite.h index b30b1053a..8878c0b9c 100644 --- a/src/Magnum/Math/CubicHermite.h +++ b/src/Magnum/Math/CubicHermite.h @@ -146,12 +146,30 @@ template class CubicHermite { /** * @brief Raw data - * @return One-dimensional array of three elements * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of three elements, i.e. + * @cpp T(&)[3] @ce. * @see @ref inTangent(), @ref point(), @ref outTangent() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return &_inTangent; } - constexpr const T* data() const { return &_inTangent; } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[3] { + return reinterpret_cast(_inTangent); + } + /* Can't be constexpr anymore, the only other solution would be to + store `T _data[3]` instead of the three variables, but that may make + the internal implementation too error prone. Similarly as with + RectangularMatrix::data(), having a statically sized array returned + is a far more useful property than constexpr, so that wins. */ + auto data() const -> const T(&)[3] { + return reinterpret_cast(_inTangent); + } + #endif /** @brief Equality comparison */ bool operator==(const CubicHermite& other) const; diff --git a/src/Magnum/Math/Dual.h b/src/Magnum/Math/Dual.h index ecac58ef1..fcf7594c8 100644 --- a/src/Magnum/Math/Dual.h +++ b/src/Magnum/Math/Dual.h @@ -113,12 +113,30 @@ template class Dual { /** * @brief Raw data - * @return One-dimensional array of two elements * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of two elements, i.e. + * @cpp T(&)[2] @ce. * @see @ref real(), @ref dual() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return &_real; } - constexpr const T* data() const { return &_real; } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[2] { + return reinterpret_cast(_real); + } + /* Can't be constexpr anymore, the only other solution would be to + store `T _data[2]` instead of the two variables, but that may make + the internal implementation too error prone. Similarly as with + RectangularMatrix::data(), having a statically sized array returned + is a far more useful property than constexpr, so that wins. */ + auto data() const -> const T(&)[2] { + return reinterpret_cast(_real); + } + #endif /** @brief Equality comparison */ bool operator==(const Dual& other) const { diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index bdbae24d6..76f229c81 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -191,12 +191,26 @@ template class DualComplex: public Dual> { /** * @brief Raw data - * @return One-dimensional array of four elements * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of four elements, i.e. + * @cpp T(&)[4] @ce. * @see @ref real(), @ref dual() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return Dual>::data()->data(); } - constexpr const T* data() const { return Dual>::data()->data(); } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[4] { + return reinterpret_cast(Dual>::data()); + } + /* Can't be constexpr anymore, see base implementation for details */ + auto data() const -> const T(&)[4] { + return reinterpret_cast(Dual>::data()); + } + #endif /** * @brief Whether the dual complex number is normalized diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index 54c01b9c7..417c99f67 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -338,12 +338,26 @@ template class DualQuaternion: public Dual> { /** * @brief Raw data - * @return One-dimensional array of eight elements * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of eight elements, i.e. + * @cpp T(&)[8] @ce. * @see @ref real(), @ref dual() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return Dual>::data()->data(); } - constexpr const T* data() const { return Dual>::data()->data(); } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[8] { + return reinterpret_cast(Dual>::data()); + } + /* Can't be constexpr anymore, see base implementation for details */ + auto data() const -> const T(&)[8] { + return reinterpret_cast(Dual>::data()); + } + #endif /** * @brief Whether the dual quaternion is normalized diff --git a/src/Magnum/Math/Frustum.h b/src/Magnum/Math/Frustum.h index 7a6ab145d..744275e8b 100644 --- a/src/Magnum/Math/Frustum.h +++ b/src/Magnum/Math/Frustum.h @@ -127,10 +127,34 @@ template class Frustum { /** * @brief Raw data - * @return One-dimensional array of length `24`. + * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of 24 elements, i.e. + * @cpp T(&)[24] @ce. + * @see @ref operator[]() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return _data[0].data(); } - constexpr const T* data() const { return _data[0].data(); } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[24] { + return reinterpret_cast(_data); + } + /* Can't really be constexpr anymore, the only other solution is having + an union with `T _rawData[24]` and return that, but in a constexpr + context it'd mean we'd have to initialize it instead of `_data` in + the constructor ... and then operator[]() could not be constexpr + anymore. I can't think of a practical use case where constexpr + data() would be needed and operator[]() could not be used instead. + Similarly to RectangularMatrix::data(), having a statically sized + array returned is a far more useful property than constexpr, so that + wins. */ + auto data() const -> const T(&)[24] { + return reinterpret_cast(_data); + } + #endif #ifdef MAGNUM_BUILD_DEPRECATED /** diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 1cfac92ac..8ef1e333d 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -362,12 +362,33 @@ template class Quaternion { /** * @brief Raw data * - * Returns one-dimensional array of four elements, vector part first, - * scalar after. + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of four elements, i.e. + * @cpp T(&)[4] @ce, vector part first, scalar after. * @see @ref vector(), @ref scalar() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return _vector.data(); } - constexpr const T* data() const { return _vector.data(); } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[4] { + return reinterpret_cast(_vector); + } + /* Can't really be constexpr anymore, the only other solution is having + an union with `T _rawData[4]` and return that, but in a constexpr + context it'd mean we'd have to initialize it instead of `_data` in + the constructor ... and then operator[]() could not be constexpr + anymore. I can't think of a practical use case where constexpr + data() would be needed and operator[]() could not be used instead. + Similarly to RectangularMatrix::data(), having a statically sized + array returned is a far more useful property than constexpr, so that + wins. */ + auto data() const -> const T(&)[4] { + return reinterpret_cast(_vector); + } + #endif /** @brief Equality comparison */ bool operator==(const Quaternion& other) const { diff --git a/src/Magnum/Math/Range.h b/src/Magnum/Math/Range.h index e4ff9de90..2bccb0281 100644 --- a/src/Magnum/Math/Range.h +++ b/src/Magnum/Math/Range.h @@ -186,14 +186,34 @@ template class Range { /** * @brief Raw data - * @return One-dimensional array of `dimensions`*2 length. - */ - T* data() { - return dataInternal(typename std::conditional::type{}); + * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of @cpp dimensions*2 @ce elements, + * i.e. @cpp T(&)[dimensions*2] @ce. + * @ref min(), @ref max() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[dimensions*2] { + return reinterpret_cast(_min); + } + /* Can't really be constexpr anymore, the only other solution is having + an union with `T _rawData[24]` and return that, but in a constexpr + context it'd mean we'd have to initialize it instead of `_data` in + the constructor ... and then operator[]() could not be constexpr + anymore. I can't think of a practical use case where constexpr + data() would be needed and operator[]() could not be used instead. + Similarly to RectangularMatrix::data(), having a statically sized + array returned is a far more useful property than constexpr, so that + wins. */ + auto data() const -> const T(&)[dimensions*2] { + return reinterpret_cast(_min); } - constexpr const T* data() const { - return dataInternal(typename std::conditional::type{}); - } /**< @overload */ + #endif /** * @brief Minimal coordinates (inclusive) @@ -328,12 +348,6 @@ template class Range { explicit Range(Magnum::NoInitT, Magnum::NoInitT*) noexcept: _min{Magnum::NoInit}, _max{Magnum::NoInit} {} explicit Range(Magnum::NoInitT, void*) noexcept {} - /* Called from data(), always returning a T* */ - constexpr const VectorType* dataInternal(void*) const { return &_min; } - VectorType* dataInternal(void*) { return &_min; } - constexpr const T* dataInternal(T*) const { return _min.data(); } - T* dataInternal(T*) { return _min.data(); } - VectorType _min, _max; }; diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 59ad03094..8d1c7cedf 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -218,13 +218,33 @@ template class RectangularMatrix { /** * @brief Raw data - * @return One-dimensional array of `cols*rows` length in column-major - * order. * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of @cpp cols*rows @ce elements, + * i.e. @cpp T(&)[cols*rows] @ce. * @see @ref operator[]() - */ - T* data() { return _data[0].data(); } - constexpr const T* data() const { return _data[0].data(); } /**< @overload */ + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[cols*rows] { + return reinterpret_cast(_data); + } + /* Can't really be constexpr anymore, the only other solution is having + an union with `T _rawData[cols*rows]` and return that, but in a + constexpr context it'd mean we'd have to initialize it instead of + `_data` in the constructor ... and then operator[]() could not be + constexpr anymore. I can't think of a practical use case where + constexpr data() would be needed and operator[]() could not be used + instead. Having a statically sized array returned is a far more + useful property than constexpr, so that wins. */ + auto data() const -> const T(&)[cols*rows] { + return reinterpret_cast(_data); + } + #endif /** * @brief Column at given position diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index 50424030c..488781b56 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -229,20 +229,23 @@ void BezierTest::data() { CORRADE_COMPARE(a[2], (Vector2{0.7f, 20.3f})); CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.0f, 0.0f}, Vector2{1.1f, 0.3f}, Vector2{0.7f, 20.3f}})); - constexpr QuadraticBezier2D b{Vector2{3.5f, 0.1f}, Vector2{1.3f, 10.3f}, Vector2{0.0f, -1.2f}}; + constexpr QuadraticBezier2D ca{Vector2{3.5f, 0.1f}, Vector2{1.3f, 10.3f}, Vector2{0.0f, -1.2f}}; #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */ constexpr #endif - Vector2 c = b[2]; + Vector2 c = ca[2]; CORRADE_COMPARE(c, (Vector2{0.0f, -1.2f})); #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */ constexpr #endif - Vector2 d = *b.data(); - Vector2 e = a.data()[2]; + Vector2 d = *ca.data(); + CORRADE_COMPARE(a.data()[2], (Vector2{0.7f, 20.3f})); CORRADE_COMPARE(d, (Vector2{3.5f, 0.1f})); - CORRADE_COMPARE(e, (Vector2{0.7f, 20.3f})); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } void BezierTest::compare() { diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp index 2db39fbe9..c2989348b 100644 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ b/src/Magnum/Math/Test/BoolVectorTest.cpp @@ -207,32 +207,37 @@ void BoolVectorTest::convert() { void BoolVectorTest::data() { /* 0b00001000, 0b00000011, 0b100 */ - constexpr BoolVector19 a(0x08, 0x03, 0x04); + constexpr BoolVector19 ca(0x08, 0x03, 0x04); - CORRADE_VERIFY(!a[0] && !a[1] && !a[2]); - CORRADE_VERIFY(a[3]); - CORRADE_VERIFY(!a[4] && !a[5] && !a[6] && !a[7]); - CORRADE_VERIFY(a[8]); - CORRADE_VERIFY(a[9]); - CORRADE_VERIFY(!a[10] && !a[11] && !a[12] && !a[13] && !a[14] && !a[15] && !a[16] && !a[17]); - CORRADE_VERIFY(a[18]); + CORRADE_VERIFY(!ca[0] && !ca[1] && !ca[2]); + CORRADE_VERIFY(ca[3]); + CORRADE_VERIFY(!ca[4] && !ca[5] && !ca[6] && !ca[7]); + CORRADE_VERIFY(ca[8]); + CORRADE_VERIFY(ca[9]); + CORRADE_VERIFY(!ca[10] && !ca[11] && !ca[12] && !ca[13] && !ca[14] && !ca[15] && !ca[16] && !ca[17]); + CORRADE_VERIFY(ca[18]); - constexpr bool b = a[9]; + constexpr bool b = ca[9]; CORRADE_COMPARE(b, true); + BoolVector19 a(0x08, 0x03, 0x04); + a.set(15, true); + CORRADE_VERIFY(a[15]); + CORRADE_COMPARE(a, BoolVector19(0x08, 0x83, 0x04)); + a.set(15, false); + CORRADE_VERIFY(!a[15]); + CORRADE_COMPARE(a, BoolVector19(0x08, 0x03, 0x04)); + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */ constexpr #endif - UnsignedByte c = *a.data(); + UnsignedByte c = *ca.data(); + CORRADE_COMPARE(a.data()[1], 0x03); CORRADE_COMPARE(c, 0x08); - BoolVector19 d(0x08, 0x03, 0x04); - d.set(15, true); - CORRADE_VERIFY(d[15]); - CORRADE_COMPARE(d, BoolVector19(0x08, 0x83, 0x04)); - d.set(15, false); - CORRADE_VERIFY(!d[15]); - CORRADE_COMPARE(d, BoolVector19(0x08, 0x03, 0x04)); + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } void BoolVectorTest::compare() { diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index c62f8cba8..0a2d09932 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -295,10 +295,14 @@ void ComplexTest::data() { a.imaginary() = -3.5f; CORRADE_COMPARE(a, (Complex{2.0f, -3.5f})); - constexpr Float b = *ca.data(); - Float c = a.data()[1]; - CORRADE_COMPARE(b, 1.5f); - CORRADE_COMPARE(c, -3.5f); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[1], -3.5f); + CORRADE_COMPARE(*ca.data(), 1.5f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 2); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 2); } void ComplexTest::compare() { diff --git a/src/Magnum/Math/Test/CubicHermiteTest.cpp b/src/Magnum/Math/Test/CubicHermiteTest.cpp index 574ae5c6c..09d8b9dda 100644 --- a/src/Magnum/Math/Test/CubicHermiteTest.cpp +++ b/src/Magnum/Math/Test/CubicHermiteTest.cpp @@ -672,10 +672,14 @@ void CubicHermiteTest::dataScalar() { a.outTangent() = 2.1f; CORRADE_COMPARE(a, (CubicHermite1D{3.0f, 1.0f, 2.1f})); - constexpr Float b = *ca.data(); - Float c = a.data()[2]; - CORRADE_COMPARE(b, 2.0f); - CORRADE_COMPARE(c, 2.1f); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(*ca.data(), 2.0f); + CORRADE_COMPARE(a.data()[2], 2.1f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } void CubicHermiteTest::dataVector() { @@ -693,10 +697,14 @@ void CubicHermiteTest::dataVector() { a.outTangent().y() = 2.0f; CORRADE_COMPARE(a, (CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}})); - constexpr Vector2 b = *ca.data(); - Vector2 c = a.data()[2]; - CORRADE_COMPARE(b, (Vector2{1.0f, 2.0f})); - CORRADE_COMPARE(c, (Vector2{3.0f, 2.0f})); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[2], (Vector2{3.0f, 2.0f})); + CORRADE_COMPARE(*ca.data(), (Vector2{1.0f, 2.0f})); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } void CubicHermiteTest::dataComplex() { @@ -714,10 +722,14 @@ void CubicHermiteTest::dataComplex() { a.outTangent().imaginary() = 2.0f; CORRADE_COMPARE(a, (CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}})); - constexpr Complex b = *ca.data(); - Complex c = a.data()[2]; - CORRADE_COMPARE(b, (Complex{1.0f, 2.0f})); - CORRADE_COMPARE(c, (Complex{3.0f, 2.0f})); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[2], (Complex{3.0f, 2.0f})); + CORRADE_COMPARE(*ca.data(), (Complex{1.0f, 2.0f})); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } void CubicHermiteTest::dataQuaternion() { @@ -745,10 +757,14 @@ void CubicHermiteTest::dataQuaternion() { {{1.5f, -2.0f, 0.1f}, 1.0f}, {{3.0f, -0.5f, 2.0f}, 0.3f}})); - constexpr Quaternion b = *ca.data(); - Quaternion c = a.data()[2]; - CORRADE_COMPARE(b, (Quaternion{{1.0f, 2.0f, -1.0f}, 3.0f})); - CORRADE_COMPARE(c, (Quaternion{{3.0f, -0.5f, 2.0f}, 0.3f})); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[2], (Quaternion{{3.0f, -0.5f, 2.0f}, 0.3f})); + CORRADE_COMPARE(*ca.data(), (Quaternion{{1.0f, 2.0f, -1.0f}, 3.0f})); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3); } void CubicHermiteTest::compareScalar() { diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index cb24a3841..4aab835e4 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -288,10 +288,14 @@ void DualComplexTest::data() { DualComplex a{{-1.0f, 2.5f}, {3.0f, -7.5f}}; - constexpr Float d = *ca.data(); - Float e = a.data()[3]; - CORRADE_COMPARE(d, -1.0f); - CORRADE_COMPARE(e, -7.5f); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(*ca.data(), -1.0f); + CORRADE_COMPARE(a.data()[3], -7.5f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4); } void DualComplexTest::isNormalized() { diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 43187f1c4..80c84f10f 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -322,13 +322,14 @@ void DualQuaternionTest::data() { DualQuaternion a{{{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f}}; - #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ - constexpr - #endif - Float d = *ca.data(); - Float e = a.data()[7]; - CORRADE_COMPARE(d, 1.0f); - CORRADE_COMPARE(e, 2.0f); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[7], 2.0f); + CORRADE_COMPARE(ca.data()[4], 0.5f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 8); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 8); } void DualQuaternionTest::isNormalized() { diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index cada3a1ce..5bbde26c0 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -208,10 +208,14 @@ void DualTest::data() { a.dual() = -3.5f; CORRADE_COMPARE(a, (Dual{2.0f, -3.5f})); - constexpr Float b = *ca.data(); - Float c = a.data()[1]; - CORRADE_COMPARE(b, 1.5f); - CORRADE_COMPARE(c, -3.5f); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(*ca.data(), 1.5f); + CORRADE_COMPARE(a.data()[1], -3.5f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 2); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 2); } void DualTest::compare() { diff --git a/src/Magnum/Math/Test/FrustumTest.cpp b/src/Magnum/Math/Test/FrustumTest.cpp index decaef02f..8bea6e78f 100644 --- a/src/Magnum/Math/Test/FrustumTest.cpp +++ b/src/Magnum/Math/Test/FrustumTest.cpp @@ -310,31 +310,42 @@ void FrustumTest::convert() { void FrustumTest::data() { /* Using default-constructed to verify that the planes are in correct order */ - constexpr Frustum a; + constexpr Frustum ca; #if !defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5 constexpr #endif - Vector4 right = a.cbegin()[1]; + Vector4 right = ca.cbegin()[1]; CORRADE_COMPARE(right, (Vector4{-1.0f, 0.0f, 0.0f, 1.0f})); - constexpr Vector4 bottom = a[2]; + constexpr Vector4 bottom = ca[2]; CORRADE_COMPARE(bottom, (Vector4{0.0f, 1.0f, 0.0f, 1.0f})); - constexpr Vector4 near = a.near(); + constexpr Vector4 near = ca.near(); CORRADE_COMPARE(near, (Vector4{0.0f, 0.0f, 1.0f, 1.0f})); #if !defined(CORRADE_MSVC2015_COMPATIBILITY) && (!defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5) constexpr #endif - Vector4 far = *(a.cend() - 1); + Vector4 far = *(ca.cend() - 1); CORRADE_COMPARE(far, (Vector4{0.0f, 0.0f, -1.0f, 1.0f})); - #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */ - constexpr - #endif - Float b = *a.data(); - CORRADE_COMPARE(b, 1.0f); + constexpr Frustum a{ + {-1.0f, 2.0f, -3.0f, 0.1f}, + { 1.0f, -2.0f, 3.0f, 0.2f}, + {-4.0f, 5.0f, -6.0f, 0.3f}, + { 4.0f, -5.0f, 6.0f, 0.4f}, + {-7.0f, 8.0f, -9.0f, 0.5f}, + { 7.0f, 8.0f, 9.0f, 0.6f}}; + + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[9], 5.0f); + CORRADE_COMPARE(ca.data()[4], -1.0f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 24); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 24); } void FrustumTest::dataOutOfRange() { diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index 54e575052..4b36c918e 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -334,13 +334,14 @@ void QuaternionTest::data() { a.scalar() = 1.1f; CORRADE_COMPARE(a, (Quaternion{{1.0f, 4.3f, 3.0f}, 1.1f})); - #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ - constexpr - #endif - Float b = *ca.data(); - Float c = a.data()[3]; - CORRADE_COMPARE(b, 1.0f); - CORRADE_COMPARE(c, 1.1f); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[3], 1.1f); + CORRADE_COMPARE(ca.data()[1], 2.0f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4); } void QuaternionTest::compare() { diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index 7ae8394aa..f2c953f46 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -111,6 +111,7 @@ struct RangeTest: Corrade::TestSuite::Tester { void constructCopy(); void convert(); + void data(); void access(); void compare(); void dimensionSlice(); @@ -167,6 +168,7 @@ RangeTest::RangeTest() { &RangeTest::constructCopy, &RangeTest::convert, + &RangeTest::data, &RangeTest::access, &RangeTest::compare, &RangeTest::dimensionSlice, @@ -425,7 +427,7 @@ void RangeTest::convert() { CORRADE_VERIFY(!std::is_convertible::value); } -void RangeTest::access() { +void RangeTest::data() { Range1Di line(34, 47); Range2Di rect({34, 23}, {47, 30}); Range3Di cube({34, 23, -17}, {47, 30, 12}); @@ -434,21 +436,32 @@ void RangeTest::access() { constexpr Range2Di crect({34, 23}, {47, 30}); constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12}); - CORRADE_COMPARE(line.data(), static_cast(&line)); - CORRADE_COMPARE(rect.data(), static_cast(&rect)); - CORRADE_COMPARE(cube.data(), static_cast(&cube)); - constexpr Int lineData = *cline.data(); - #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ - constexpr - #endif - Int rectData = *crect.data(); - #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ - constexpr - #endif - Int cubeData = *ccube.data(); - CORRADE_COMPARE(lineData, 34); - CORRADE_COMPARE(rectData, 34); - CORRADE_COMPARE(cubeData, 34); + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(line.data()[1], 47); + CORRADE_COMPARE(cline.data()[1], 47); + CORRADE_COMPARE(*rect.data(), 34); + CORRADE_COMPARE(*crect.data(), 34); + CORRADE_COMPARE(cube.data()[2], -17); + CORRADE_COMPARE(ccube.data()[2], -17); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(line.data()), 2); + CORRADE_COMPARE(Corrade::Containers::arraySize(cline.data()), 2); + CORRADE_COMPARE(Corrade::Containers::arraySize(rect.data()), 4); + CORRADE_COMPARE(Corrade::Containers::arraySize(crect.data()), 4); + CORRADE_COMPARE(Corrade::Containers::arraySize(cube.data()), 6); + CORRADE_COMPARE(Corrade::Containers::arraySize(ccube.data()), 6); +} + +void RangeTest::access() { + Range1Di line(34, 47); + Range2Di rect({34, 23}, {47, 30}); + Range3Di cube({34, 23, -17}, {47, 30, 12}); + + constexpr Range1Di cline(34, 47); + constexpr Range2Di crect({34, 23}, {47, 30}); + constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12}); CORRADE_COMPARE(line.min(), 34); CORRADE_COMPARE(cline.min(), 34); diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 149dbb6ee..b468156f8 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -402,37 +402,40 @@ void RectangularMatrixTest::convert() { } void RectangularMatrixTest::data() { - Matrix3x4 m; + Matrix3x4 a; Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f); - m[2] = vector; - m[1][1] = 1.0f; - m[0][2] = 1.5f; + a[2] = vector; + a[1][1] = 1.0f; + a[0][2] = 1.5f; - CORRADE_COMPARE(m[1][1], 1.0f); - CORRADE_COMPARE(m[0][2], 1.5f); - CORRADE_COMPARE(m[2], vector); + CORRADE_COMPARE(a[1][1], 1.0f); + CORRADE_COMPARE(a[0][2], 1.5f); + CORRADE_COMPARE(a[2], vector); - CORRADE_COMPARE(m, Matrix3x4(Vector4(0.0f, 0.0f, 1.5f, 0.0f), + CORRADE_COMPARE(a, Matrix3x4(Vector4(0.0f, 0.0f, 1.5f, 0.0f), Vector4(0.0f, 1.0f, 0.0f, 0.0f), Vector4(4.0f, 5.0f, 6.0f, 7.0f))); - /* Pointer chasings, i.e. *(b.data()[1]), are not possible */ - constexpr Matrix3x4 a(Vector4(3.0f, 5.0f, 8.0f, 4.0f), - Vector4(4.5f, 4.0f, 7.0f, 3.0f), - Vector4(7.0f, -1.7f, 8.0f, 0.0f)); + constexpr Matrix3x4 ca(Vector4(3.0f, 5.0f, 8.0f, 4.0f), + Vector4(4.5f, 4.0f, 7.0f, 3.0f), + Vector4(7.0f, -1.7f, 8.0f, 0.0f)); #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */ constexpr #endif - Vector4 b = a[2]; - constexpr Float c = a[1][2]; - #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */ - constexpr - #endif - Float d = *a.data(); + Vector4 b = ca[2]; + constexpr Float c = ca[1][2]; CORRADE_COMPARE(b, Vector4(7.0f, -1.7f, 8.0f, 0.0f)); CORRADE_COMPARE(c, 7.0f); - CORRADE_COMPARE(d, 3.0f); + + /* Not constexpr anymore, as it has to reinterpret to return a + correctly-sized array */ + CORRADE_COMPARE(a.data()[8], 4.0f); + CORRADE_COMPARE(ca.data()[1], 5.0f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 12); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 12); } void RectangularMatrixTest::row() { diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 23450bdfc..e79c695c1 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -341,23 +341,29 @@ void VectorTest::isNormalized() { } void VectorTest::data() { - Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f); - vector[2] = 1.0f; - vector[3] = 1.5f; + Vector4 a(4.0f, 5.0f, 6.0f, 7.0f); + a[2] = 1.0f; + a[3] = 1.5f; - CORRADE_COMPARE(vector[2], 1.0f); - CORRADE_COMPARE(vector[3], 1.5f); - CORRADE_COMPARE(vector, Vector4(4.0f, 5.0f, 1.0f, 1.5f)); + CORRADE_COMPARE(a[2], 1.0f); + CORRADE_COMPARE(a[3], 1.5f); + CORRADE_COMPARE(a, Vector4(4.0f, 5.0f, 1.0f, 1.5f)); + + constexpr Vector4 ca(1.0f, 2.0f, -3.0f, 4.5f); + constexpr Float f = ca[3]; + CORRADE_COMPARE(f, 4.5f); /* Pointer chasings, i.e. *(b.data()[3]), are not possible */ - constexpr Vector4 a(1.0f, 2.0f, -3.0f, 4.5f); - constexpr Float f = a[3]; #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ constexpr #endif - Float g = *a.data(); - CORRADE_COMPARE(f, 4.5f); + Float g = *ca.data(); + CORRADE_COMPARE(a.data()[1], 5.0f); CORRADE_COMPARE(g, 1.0f); + + /* It actually returns an array */ + CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4); + CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4); } void VectorTest::compare() { diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 57d3ec4e6..1f13f6c05 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -233,12 +233,21 @@ template class Vector { /** * @brief Raw data - * @return One-dimensional array of `size` length. * + * Contrary to what Doxygen shows, returns reference to an + * one-dimensional fixed-size array of `size` elements, i.e. + * @cpp T(&)[size] @ce. * @see @ref operator[]() + * @todoc Fix once there's a possibility to patch the signature in a + * post-processing step (https://github.com/mosra/m.css/issues/56) */ - T* data() { return _data; } - constexpr const T* data() const { return _data; } /**< @overload */ + #ifdef DOXYGEN_GENERATING_OUTPUT + T* data(); + constexpr const T* data() const; /**< @overload */ + #else + auto data() -> T(&)[size] { return _data; } + constexpr auto data() const -> const T(&)[size] { return _data; } + #endif /** * @brief Value at given position