Browse Source

Math: return an array reference instead of a pointer from data().

This makes it possible to conveniently do things like

    Containers::StridedArrayView1D<Float> array = …;
    Vector4 vector{NoInit};
    Utility::copy(array, vector); // or the other way around

which is especially useful together with the new JSON classes. In some
cases this means the function is no longer constexpr, but those weren't
constexpr because it was useful for anything, they were only because it
was possible. So this breakage shouldn't do any harm I think.
pull/554/head
Vladimír Vondruš 4 years ago
parent
commit
d474f9d176
  1. 16
      doc/changelog.dox
  2. 15
      src/Magnum/Math/Bezier.h
  3. 15
      src/Magnum/Math/BoolVector.h
  4. 26
      src/Magnum/Math/Complex.h
  5. 24
      src/Magnum/Math/CubicHermite.h
  6. 24
      src/Magnum/Math/Dual.h
  7. 20
      src/Magnum/Math/DualComplex.h
  8. 20
      src/Magnum/Math/DualQuaternion.h
  9. 30
      src/Magnum/Math/Frustum.h
  10. 29
      src/Magnum/Math/Quaternion.h
  11. 40
      src/Magnum/Math/Range.h
  12. 30
      src/Magnum/Math/RectangularMatrix.h
  13. 13
      src/Magnum/Math/Test/BezierTest.cpp
  14. 39
      src/Magnum/Math/Test/BoolVectorTest.cpp
  15. 12
      src/Magnum/Math/Test/ComplexTest.cpp
  16. 48
      src/Magnum/Math/Test/CubicHermiteTest.cpp
  17. 12
      src/Magnum/Math/Test/DualComplexTest.cpp
  18. 15
      src/Magnum/Math/Test/DualQuaternionTest.cpp
  19. 12
      src/Magnum/Math/Test/DualTest.cpp
  20. 31
      src/Magnum/Math/Test/FrustumTest.cpp
  21. 15
      src/Magnum/Math/Test/QuaternionTest.cpp
  22. 45
      src/Magnum/Math/Test/RangeTest.cpp
  23. 41
      src/Magnum/Math/Test/RectangularMatrixTest.cpp
  24. 26
      src/Magnum/Math/Test/VectorTest.cpp
  25. 15
      src/Magnum/Math/Vector.h

16
doc/changelog.dox

@ -385,6 +385,15 @@ See also:
matrices, and with the default on @ref Math::RectangularMatrix being matrices, and with the default on @ref Math::RectangularMatrix being
zero-fill while @ref Math::Matrix stays with the identity for consistency zero-fill while @ref Math::Matrix stays with the identity for consistency
with other constructors. 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 @subsubsection changelog-latest-changes-meshtools MeshTools library
@ -946,6 +955,13 @@ See also:
process. Existing code that calls these with unsanitized inputs now process. Existing code that calls these with unsanitized inputs now
additionally needs to account for reflection as suggested in the additionally needs to account for reflection as suggested in the
documentation. 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 - @ref SceneGraph::Object::addChild() no longer requires the type constructor
to have the last parameter a parent object object pointer, as that was to have the last parameter a parent object object pointer, as that was
quite limiting. Instead it's calling @ref SceneGraph::Object::setParent() quite limiting. Instead it's calling @ref SceneGraph::Object::setParent()

15
src/Magnum/Math/Bezier.h

@ -137,12 +137,21 @@ template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier {
/** /**
* @brief Raw data * @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[]() * @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<dimensions, T>* data() { return _data; } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const Vector<dimensions, T>* data() const { return _data; } /**< @overload */ Vector<dimensions, T>* data();
constexpr const Vector<dimensions, T>* data() const; /**< @overload */
#else
auto data() -> Vector<dimensions, T>(&)[order + 1] { return _data; }
constexpr auto data() const -> const Vector<dimensions, T>(&)[order + 1] { return _data; }
#endif
/** @brief Equality comparison */ /** @brief Equality comparison */
bool operator==(const Bezier<order, dimensions, T>& other) const { bool operator==(const Bezier<order, dimensions, T>& other) const {

15
src/Magnum/Math/BoolVector.h

@ -130,12 +130,21 @@ template<std::size_t size> class BoolVector {
/** /**
* @brief Raw data * @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() * @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; } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const UnsignedByte* data() const { return _data; } /**< @overload */ 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 */ /** @brief Bit at given position */
constexpr bool operator[](std::size_t i) const { constexpr bool operator[](std::size_t i) const {

26
src/Magnum/Math/Complex.h

@ -183,12 +183,30 @@ template<class T> class Complex {
/** /**
* @brief Raw data * @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() * @see @ref real(), @ref imaginary()
*/ * @todoc Fix once there's a possibility to patch the signature in a
T* data() { return &_real; } * post-processing step (https://github.com/mosra/m.css/issues/56)
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<T(&)[2]>(_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<const T(&)[2]>(_real);
}
#endif
/** @brief Equality comparison */ /** @brief Equality comparison */
bool operator==(const Complex<T>& other) const { bool operator==(const Complex<T>& other) const {

24
src/Magnum/Math/CubicHermite.h

@ -146,12 +146,30 @@ template<class T> class CubicHermite {
/** /**
* @brief Raw data * @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() * @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; } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return &_inTangent; } /**< @overload */ T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[3] {
return reinterpret_cast<T(&)[3]>(_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<const T(&)[3]>(_inTangent);
}
#endif
/** @brief Equality comparison */ /** @brief Equality comparison */
bool operator==(const CubicHermite<T>& other) const; bool operator==(const CubicHermite<T>& other) const;

24
src/Magnum/Math/Dual.h

@ -113,12 +113,30 @@ template<class T> class Dual {
/** /**
* @brief Raw data * @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() * @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; } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return &_real; } /**< @overload */ T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[2] {
return reinterpret_cast<T(&)[2]>(_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<const T(&)[2]>(_real);
}
#endif
/** @brief Equality comparison */ /** @brief Equality comparison */
bool operator==(const Dual<T>& other) const { bool operator==(const Dual<T>& other) const {

20
src/Magnum/Math/DualComplex.h

@ -191,12 +191,26 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
/** /**
* @brief Raw data * @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() * @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<Complex<T>>::data()->data(); } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return Dual<Complex<T>>::data()->data(); } /**< @overload */ T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[4] {
return reinterpret_cast<T(&)[4]>(Dual<Complex<T>>::data());
}
/* Can't be constexpr anymore, see base implementation for details */
auto data() const -> const T(&)[4] {
return reinterpret_cast<const T(&)[4]>(Dual<Complex<T>>::data());
}
#endif
/** /**
* @brief Whether the dual complex number is normalized * @brief Whether the dual complex number is normalized

20
src/Magnum/Math/DualQuaternion.h

@ -338,12 +338,26 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Raw data * @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() * @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<Quaternion<T>>::data()->data(); } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return Dual<Quaternion<T>>::data()->data(); } /**< @overload */ T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[8] {
return reinterpret_cast<T(&)[8]>(Dual<Quaternion<T>>::data());
}
/* Can't be constexpr anymore, see base implementation for details */
auto data() const -> const T(&)[8] {
return reinterpret_cast<const T(&)[8]>(Dual<Quaternion<T>>::data());
}
#endif
/** /**
* @brief Whether the dual quaternion is normalized * @brief Whether the dual quaternion is normalized

30
src/Magnum/Math/Frustum.h

@ -127,10 +127,34 @@ template<class T> class Frustum {
/** /**
* @brief Raw data * @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(); } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return _data[0].data(); } /**< @overload */ T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[24] {
return reinterpret_cast<T(&)[24]>(_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<const T(&)[24]>(_data);
}
#endif
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**

29
src/Magnum/Math/Quaternion.h

@ -362,12 +362,33 @@ template<class T> class Quaternion {
/** /**
* @brief Raw data * @brief Raw data
* *
* Returns one-dimensional array of four elements, vector part first, * Contrary to what Doxygen shows, returns reference to an
* scalar after. * one-dimensional fixed-size array of four elements, i.e.
* @cpp T(&)[4] @ce, vector part first, scalar after.
* @see @ref vector(), @ref scalar() * @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(); } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return _vector.data(); } /**< @overload */ T* data();
const T* data() const; /**< @overload */
#else
auto data() -> T(&)[4] {
return reinterpret_cast<T(&)[4]>(_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<const T(&)[4]>(_vector);
}
#endif
/** @brief Equality comparison */ /** @brief Equality comparison */
bool operator==(const Quaternion<T>& other) const { bool operator==(const Quaternion<T>& other) const {

40
src/Magnum/Math/Range.h

@ -186,14 +186,34 @@ template<UnsignedInt dimensions, class T> class Range {
/** /**
* @brief Raw data * @brief Raw data
* @return One-dimensional array of `dimensions`*2 length. *
*/ * Contrary to what Doxygen shows, returns reference to an
T* data() { * one-dimensional fixed-size array of @cpp dimensions*2 @ce elements,
return dataInternal(typename std::conditional<dimensions == 1, void*, T*>::type{}); * 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<T(&)[dimensions*2]>(_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<const T(&)[dimensions*2]>(_min);
} }
constexpr const T* data() const { #endif
return dataInternal(typename std::conditional<dimensions == 1, void*, T*>::type{});
} /**< @overload */
/** /**
* @brief Minimal coordinates (inclusive) * @brief Minimal coordinates (inclusive)
@ -328,12 +348,6 @@ template<UnsignedInt dimensions, class T> class Range {
explicit Range(Magnum::NoInitT, Magnum::NoInitT*) noexcept: _min{Magnum::NoInit}, _max{Magnum::NoInit} {} explicit Range(Magnum::NoInitT, Magnum::NoInitT*) noexcept: _min{Magnum::NoInit}, _max{Magnum::NoInit} {}
explicit Range(Magnum::NoInitT, void*) noexcept {} 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; VectorType _min, _max;
}; };

30
src/Magnum/Math/RectangularMatrix.h

@ -218,13 +218,33 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Raw data * @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[]() * @see @ref operator[]()
*/ * @todoc Fix once there's a possibility to patch the signature in a
T* data() { return _data[0].data(); } * post-processing step (https://github.com/mosra/m.css/issues/56)
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(&)[cols*rows] {
return reinterpret_cast<T(&)[cols*rows]>(_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<const T(&)[cols*rows]>(_data);
}
#endif
/** /**
* @brief Column at given position * @brief Column at given position

13
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[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}})); 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? */ #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */
constexpr constexpr
#endif #endif
Vector2 c = b[2]; Vector2 c = ca[2];
CORRADE_COMPARE(c, (Vector2{0.0f, -1.2f})); CORRADE_COMPARE(c, (Vector2{0.0f, -1.2f}));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */ #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Why? */
constexpr constexpr
#endif #endif
Vector2 d = *b.data(); Vector2 d = *ca.data();
Vector2 e = a.data()[2]; CORRADE_COMPARE(a.data()[2], (Vector2{0.7f, 20.3f}));
CORRADE_COMPARE(d, (Vector2{3.5f, 0.1f})); 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() { void BezierTest::compare() {

39
src/Magnum/Math/Test/BoolVectorTest.cpp

@ -207,32 +207,37 @@ void BoolVectorTest::convert() {
void BoolVectorTest::data() { void BoolVectorTest::data() {
/* 0b00001000, 0b00000011, 0b100 */ /* 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(!ca[0] && !ca[1] && !ca[2]);
CORRADE_VERIFY(a[3]); CORRADE_VERIFY(ca[3]);
CORRADE_VERIFY(!a[4] && !a[5] && !a[6] && !a[7]); CORRADE_VERIFY(!ca[4] && !ca[5] && !ca[6] && !ca[7]);
CORRADE_VERIFY(a[8]); CORRADE_VERIFY(ca[8]);
CORRADE_VERIFY(a[9]); CORRADE_VERIFY(ca[9]);
CORRADE_VERIFY(!a[10] && !a[11] && !a[12] && !a[13] && !a[14] && !a[15] && !a[16] && !a[17]); CORRADE_VERIFY(!ca[10] && !ca[11] && !ca[12] && !ca[13] && !ca[14] && !ca[15] && !ca[16] && !ca[17]);
CORRADE_VERIFY(a[18]); CORRADE_VERIFY(ca[18]);
constexpr bool b = a[9]; constexpr bool b = ca[9];
CORRADE_COMPARE(b, true); 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 */ #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr constexpr
#endif #endif
UnsignedByte c = *a.data(); UnsignedByte c = *ca.data();
CORRADE_COMPARE(a.data()[1], 0x03);
CORRADE_COMPARE(c, 0x08); CORRADE_COMPARE(c, 0x08);
BoolVector19 d(0x08, 0x03, 0x04); /* It actually returns an array */
d.set(15, true); CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 3);
CORRADE_VERIFY(d[15]); CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 3);
CORRADE_COMPARE(d, BoolVector19(0x08, 0x83, 0x04));
d.set(15, false);
CORRADE_VERIFY(!d[15]);
CORRADE_COMPARE(d, BoolVector19(0x08, 0x03, 0x04));
} }
void BoolVectorTest::compare() { void BoolVectorTest::compare() {

12
src/Magnum/Math/Test/ComplexTest.cpp

@ -295,10 +295,14 @@ void ComplexTest::data() {
a.imaginary() = -3.5f; a.imaginary() = -3.5f;
CORRADE_COMPARE(a, (Complex{2.0f, -3.5f})); CORRADE_COMPARE(a, (Complex{2.0f, -3.5f}));
constexpr Float b = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Float c = a.data()[1]; correctly-sized array */
CORRADE_COMPARE(b, 1.5f); CORRADE_COMPARE(a.data()[1], -3.5f);
CORRADE_COMPARE(c, -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() { void ComplexTest::compare() {

48
src/Magnum/Math/Test/CubicHermiteTest.cpp

@ -672,10 +672,14 @@ void CubicHermiteTest::dataScalar() {
a.outTangent() = 2.1f; a.outTangent() = 2.1f;
CORRADE_COMPARE(a, (CubicHermite1D{3.0f, 1.0f, 2.1f})); CORRADE_COMPARE(a, (CubicHermite1D{3.0f, 1.0f, 2.1f}));
constexpr Float b = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Float c = a.data()[2]; correctly-sized array */
CORRADE_COMPARE(b, 2.0f); CORRADE_COMPARE(*ca.data(), 2.0f);
CORRADE_COMPARE(c, 2.1f); 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() { void CubicHermiteTest::dataVector() {
@ -693,10 +697,14 @@ void CubicHermiteTest::dataVector() {
a.outTangent().y() = 2.0f; a.outTangent().y() = 2.0f;
CORRADE_COMPARE(a, (CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}})); CORRADE_COMPARE(a, (CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}));
constexpr Vector2 b = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Vector2 c = a.data()[2]; correctly-sized array */
CORRADE_COMPARE(b, (Vector2{1.0f, 2.0f})); CORRADE_COMPARE(a.data()[2], (Vector2{3.0f, 2.0f}));
CORRADE_COMPARE(c, (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() { void CubicHermiteTest::dataComplex() {
@ -714,10 +722,14 @@ void CubicHermiteTest::dataComplex() {
a.outTangent().imaginary() = 2.0f; a.outTangent().imaginary() = 2.0f;
CORRADE_COMPARE(a, (CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}})); CORRADE_COMPARE(a, (CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}));
constexpr Complex b = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Complex c = a.data()[2]; correctly-sized array */
CORRADE_COMPARE(b, (Complex{1.0f, 2.0f})); CORRADE_COMPARE(a.data()[2], (Complex{3.0f, 2.0f}));
CORRADE_COMPARE(c, (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() { void CubicHermiteTest::dataQuaternion() {
@ -745,10 +757,14 @@ void CubicHermiteTest::dataQuaternion() {
{{1.5f, -2.0f, 0.1f}, 1.0f}, {{1.5f, -2.0f, 0.1f}, 1.0f},
{{3.0f, -0.5f, 2.0f}, 0.3f}})); {{3.0f, -0.5f, 2.0f}, 0.3f}}));
constexpr Quaternion b = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Quaternion c = a.data()[2]; correctly-sized array */
CORRADE_COMPARE(b, (Quaternion{{1.0f, 2.0f, -1.0f}, 3.0f})); CORRADE_COMPARE(a.data()[2], (Quaternion{{3.0f, -0.5f, 2.0f}, 0.3f}));
CORRADE_COMPARE(c, (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() { void CubicHermiteTest::compareScalar() {

12
src/Magnum/Math/Test/DualComplexTest.cpp

@ -288,10 +288,14 @@ void DualComplexTest::data() {
DualComplex a{{-1.0f, 2.5f}, {3.0f, -7.5f}}; DualComplex a{{-1.0f, 2.5f}, {3.0f, -7.5f}};
constexpr Float d = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Float e = a.data()[3]; correctly-sized array */
CORRADE_COMPARE(d, -1.0f); CORRADE_COMPARE(*ca.data(), -1.0f);
CORRADE_COMPARE(e, -7.5f); 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() { void DualComplexTest::isNormalized() {

15
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}}; 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 */ /* Not constexpr anymore, as it has to reinterpret to return a
constexpr correctly-sized array */
#endif CORRADE_COMPARE(a.data()[7], 2.0f);
Float d = *ca.data(); CORRADE_COMPARE(ca.data()[4], 0.5f);
Float e = a.data()[7];
CORRADE_COMPARE(d, 1.0f); /* It actually returns an array */
CORRADE_COMPARE(e, 2.0f); CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 8);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 8);
} }
void DualQuaternionTest::isNormalized() { void DualQuaternionTest::isNormalized() {

12
src/Magnum/Math/Test/DualTest.cpp

@ -208,10 +208,14 @@ void DualTest::data() {
a.dual() = -3.5f; a.dual() = -3.5f;
CORRADE_COMPARE(a, (Dual{2.0f, -3.5f})); CORRADE_COMPARE(a, (Dual{2.0f, -3.5f}));
constexpr Float b = *ca.data(); /* Not constexpr anymore, as it has to reinterpret to return a
Float c = a.data()[1]; correctly-sized array */
CORRADE_COMPARE(b, 1.5f); CORRADE_COMPARE(*ca.data(), 1.5f);
CORRADE_COMPARE(c, -3.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() { void DualTest::compare() {

31
src/Magnum/Math/Test/FrustumTest.cpp

@ -310,31 +310,42 @@ void FrustumTest::convert() {
void FrustumTest::data() { void FrustumTest::data() {
/* Using default-constructed to verify that the planes are in correct order */ /* 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 #if !defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5
constexpr constexpr
#endif #endif
Vector4 right = a.cbegin()[1]; Vector4 right = ca.cbegin()[1];
CORRADE_COMPARE(right, (Vector4{-1.0f, 0.0f, 0.0f, 1.0f})); 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})); 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})); 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) #if !defined(CORRADE_MSVC2015_COMPATIBILITY) && (!defined(CORRADE_TARGET_GCC) || defined(CORRADE_TARGET_CLANG) || __GNUC__ >= 5)
constexpr constexpr
#endif #endif
Vector4 far = *(a.cend() - 1); Vector4 far = *(ca.cend() - 1);
CORRADE_COMPARE(far, (Vector4{0.0f, 0.0f, -1.0f, 1.0f})); CORRADE_COMPARE(far, (Vector4{0.0f, 0.0f, -1.0f, 1.0f}));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */ constexpr Frustum a{
constexpr {-1.0f, 2.0f, -3.0f, 0.1f},
#endif { 1.0f, -2.0f, 3.0f, 0.2f},
Float b = *a.data(); {-4.0f, 5.0f, -6.0f, 0.3f},
CORRADE_COMPARE(b, 1.0f); { 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() { void FrustumTest::dataOutOfRange() {

15
src/Magnum/Math/Test/QuaternionTest.cpp

@ -334,13 +334,14 @@ void QuaternionTest::data() {
a.scalar() = 1.1f; a.scalar() = 1.1f;
CORRADE_COMPARE(a, (Quaternion{{1.0f, 4.3f, 3.0f}, 1.1f})); CORRADE_COMPARE(a, (Quaternion{{1.0f, 4.3f, 3.0f}, 1.1f}));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ /* Not constexpr anymore, as it has to reinterpret to return a
constexpr correctly-sized array */
#endif CORRADE_COMPARE(a.data()[3], 1.1f);
Float b = *ca.data(); CORRADE_COMPARE(ca.data()[1], 2.0f);
Float c = a.data()[3];
CORRADE_COMPARE(b, 1.0f); /* It actually returns an array */
CORRADE_COMPARE(c, 1.1f); CORRADE_COMPARE(Corrade::Containers::arraySize(a.data()), 4);
CORRADE_COMPARE(Corrade::Containers::arraySize(ca.data()), 4);
} }
void QuaternionTest::compare() { void QuaternionTest::compare() {

45
src/Magnum/Math/Test/RangeTest.cpp

@ -111,6 +111,7 @@ struct RangeTest: Corrade::TestSuite::Tester {
void constructCopy(); void constructCopy();
void convert(); void convert();
void data();
void access(); void access();
void compare(); void compare();
void dimensionSlice(); void dimensionSlice();
@ -167,6 +168,7 @@ RangeTest::RangeTest() {
&RangeTest::constructCopy, &RangeTest::constructCopy,
&RangeTest::convert, &RangeTest::convert,
&RangeTest::data,
&RangeTest::access, &RangeTest::access,
&RangeTest::compare, &RangeTest::compare,
&RangeTest::dimensionSlice, &RangeTest::dimensionSlice,
@ -425,7 +427,7 @@ void RangeTest::convert() {
CORRADE_VERIFY(!std::is_convertible<Range3D, Box>::value); CORRADE_VERIFY(!std::is_convertible<Range3D, Box>::value);
} }
void RangeTest::access() { void RangeTest::data() {
Range1Di line(34, 47); Range1Di line(34, 47);
Range2Di rect({34, 23}, {47, 30}); Range2Di rect({34, 23}, {47, 30});
Range3Di cube({34, 23, -17}, {47, 30, 12}); Range3Di cube({34, 23, -17}, {47, 30, 12});
@ -434,21 +436,32 @@ void RangeTest::access() {
constexpr Range2Di crect({34, 23}, {47, 30}); constexpr Range2Di crect({34, 23}, {47, 30});
constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12}); constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12});
CORRADE_COMPARE(line.data(), static_cast<void*>(&line)); /* Not constexpr anymore, as it has to reinterpret to return a
CORRADE_COMPARE(rect.data(), static_cast<void*>(&rect)); correctly-sized array */
CORRADE_COMPARE(cube.data(), static_cast<void*>(&cube)); CORRADE_COMPARE(line.data()[1], 47);
constexpr Int lineData = *cline.data(); CORRADE_COMPARE(cline.data()[1], 47);
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */ CORRADE_COMPARE(*rect.data(), 34);
constexpr CORRADE_COMPARE(*crect.data(), 34);
#endif CORRADE_COMPARE(cube.data()[2], -17);
Int rectData = *crect.data(); CORRADE_COMPARE(ccube.data()[2], -17);
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr /* It actually returns an array */
#endif CORRADE_COMPARE(Corrade::Containers::arraySize(line.data()), 2);
Int cubeData = *ccube.data(); CORRADE_COMPARE(Corrade::Containers::arraySize(cline.data()), 2);
CORRADE_COMPARE(lineData, 34); CORRADE_COMPARE(Corrade::Containers::arraySize(rect.data()), 4);
CORRADE_COMPARE(rectData, 34); CORRADE_COMPARE(Corrade::Containers::arraySize(crect.data()), 4);
CORRADE_COMPARE(cubeData, 34); 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(line.min(), 34);
CORRADE_COMPARE(cline.min(), 34); CORRADE_COMPARE(cline.min(), 34);

41
src/Magnum/Math/Test/RectangularMatrixTest.cpp

@ -402,37 +402,40 @@ void RectangularMatrixTest::convert() {
} }
void RectangularMatrixTest::data() { void RectangularMatrixTest::data() {
Matrix3x4 m; Matrix3x4 a;
Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f); Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f);
m[2] = vector; a[2] = vector;
m[1][1] = 1.0f; a[1][1] = 1.0f;
m[0][2] = 1.5f; a[0][2] = 1.5f;
CORRADE_COMPARE(m[1][1], 1.0f); CORRADE_COMPARE(a[1][1], 1.0f);
CORRADE_COMPARE(m[0][2], 1.5f); CORRADE_COMPARE(a[0][2], 1.5f);
CORRADE_COMPARE(m[2], vector); 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(0.0f, 1.0f, 0.0f, 0.0f),
Vector4(4.0f, 5.0f, 6.0f, 7.0f))); Vector4(4.0f, 5.0f, 6.0f, 7.0f)));
/* Pointer chasings, i.e. *(b.data()[1]), are not possible */ constexpr Matrix3x4 ca(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
constexpr Matrix3x4 a(Vector4(3.0f, 5.0f, 8.0f, 4.0f), Vector4(4.5f, 4.0f, 7.0f, 3.0f),
Vector4(4.5f, 4.0f, 7.0f, 3.0f), Vector4(7.0f, -1.7f, 8.0f, 0.0f));
Vector4(7.0f, -1.7f, 8.0f, 0.0f));
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */ #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Probably because copy is not constexpr */
constexpr constexpr
#endif #endif
Vector4 b = a[2]; Vector4 b = ca[2];
constexpr Float c = a[1][2]; constexpr Float c = ca[1][2];
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing pointer is verboten */
constexpr
#endif
Float d = *a.data();
CORRADE_COMPARE(b, Vector4(7.0f, -1.7f, 8.0f, 0.0f)); CORRADE_COMPARE(b, Vector4(7.0f, -1.7f, 8.0f, 0.0f));
CORRADE_COMPARE(c, 7.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() { void RectangularMatrixTest::row() {

26
src/Magnum/Math/Test/VectorTest.cpp

@ -341,23 +341,29 @@ void VectorTest::isNormalized() {
} }
void VectorTest::data() { void VectorTest::data() {
Vector4 vector(4.0f, 5.0f, 6.0f, 7.0f); Vector4 a(4.0f, 5.0f, 6.0f, 7.0f);
vector[2] = 1.0f; a[2] = 1.0f;
vector[3] = 1.5f; a[3] = 1.5f;
CORRADE_COMPARE(vector[2], 1.0f); CORRADE_COMPARE(a[2], 1.0f);
CORRADE_COMPARE(vector[3], 1.5f); CORRADE_COMPARE(a[3], 1.5f);
CORRADE_COMPARE(vector, Vector4(4.0f, 5.0f, 1.0f, 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 */ /* 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 */ #ifndef CORRADE_MSVC2015_COMPATIBILITY /* Apparently dereferencing a pointer is verboten */
constexpr constexpr
#endif #endif
Float g = *a.data(); Float g = *ca.data();
CORRADE_COMPARE(f, 4.5f); CORRADE_COMPARE(a.data()[1], 5.0f);
CORRADE_COMPARE(g, 1.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() { void VectorTest::compare() {

15
src/Magnum/Math/Vector.h

@ -233,12 +233,21 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Raw data * @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[]() * @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; } #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr const T* data() const { return _data; } /**< @overload */ 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 * @brief Value at given position

Loading…
Cancel
Save