From 36ba5f43337cd8231b6ae633523f0991d660037b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 12 Apr 2019 22:35:44 +0200 Subject: [PATCH] Math: ensure ZeroInit and IdentityInit constructors are explicit. Like NoInit ones. Not sure what I was doing there. --- doc/changelog.dox | 3 ++ src/Magnum/Math/Angle.h | 22 ++++++++++++--- src/Magnum/Math/Bezier.h | 11 ++++++-- src/Magnum/Math/BoolVector.h | 9 +++++- src/Magnum/Math/Color.h | 28 +++++++++++++++---- src/Magnum/Math/Complex.h | 9 +++++- src/Magnum/Math/Dual.h | 6 ++-- src/Magnum/Math/DualComplex.h | 11 ++++++-- src/Magnum/Math/DualQuaternion.h | 9 +++++- src/Magnum/Math/Frustum.h | 9 +++++- src/Magnum/Math/Half.h | 7 +++-- src/Magnum/Math/Matrix.h | 11 ++++++-- src/Magnum/Math/Matrix3.h | 11 ++++++-- src/Magnum/Math/Matrix4.h | 11 ++++++-- src/Magnum/Math/Quaternion.h | 9 +++++- src/Magnum/Math/Range.h | 27 ++++++++++++++++-- src/Magnum/Math/RectangularMatrix.h | 9 +++++- src/Magnum/Math/Test/AngleTest.cpp | 4 +++ src/Magnum/Math/Test/BezierTest.cpp | 3 ++ src/Magnum/Math/Test/BoolVectorTest.cpp | 3 ++ src/Magnum/Math/Test/ColorTest.cpp | 15 +++++++--- src/Magnum/Math/Test/ComplexTest.cpp | 6 ++++ src/Magnum/Math/Test/CubicHermiteTest.cpp | 18 ++++++++++++ src/Magnum/Math/Test/DualComplexTest.cpp | 6 ++++ src/Magnum/Math/Test/DualQuaternionTest.cpp | 6 ++++ src/Magnum/Math/Test/DualTest.cpp | 4 +++ src/Magnum/Math/Test/FrustumTest.cpp | 3 ++ src/Magnum/Math/Test/HalfTest.cpp | 3 ++ src/Magnum/Math/Test/Matrix3Test.cpp | 6 ++++ src/Magnum/Math/Test/Matrix4Test.cpp | 6 ++++ src/Magnum/Math/Test/MatrixTest.cpp | 6 ++++ src/Magnum/Math/Test/QuaternionTest.cpp | 6 ++++ src/Magnum/Math/Test/RangeTest.cpp | 5 ++++ .../Math/Test/RectangularMatrixTest.cpp | 3 ++ src/Magnum/Math/Test/UnitTest.cpp | 3 ++ src/Magnum/Math/Test/Vector2Test.cpp | 3 ++ src/Magnum/Math/Test/Vector3Test.cpp | 3 ++ src/Magnum/Math/Test/Vector4Test.cpp | 3 ++ src/Magnum/Math/Test/VectorTest.cpp | 3 ++ src/Magnum/Math/Unit.h | 9 +++++- src/Magnum/Math/Vector.h | 9 +++++- src/Magnum/Math/Vector2.h | 9 +++++- src/Magnum/Math/Vector3.h | 9 +++++- src/Magnum/Math/Vector4.h | 9 +++++- 44 files changed, 323 insertions(+), 42 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 4ae22ea91..041a05009 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -187,6 +187,9 @@ See also: - @ref Math::BoolVector now implements component-wise @cpp && @ce, @cpp || @ce and @cpp ! @ce for better consistency with boolean operations done on scalar types +- Construction using @ref Math::ZeroInit and @ref Math::IdentityInit is + now explicit, to be consistent with @ref Math::NoInit construction and + avoid ambiguous cases @subsubsection changelog-latest-changes-meshtools MeshTools library diff --git a/src/Magnum/Math/Angle.h b/src/Magnum/Math/Angle.h index 8fac27fd7..43a3270ef 100644 --- a/src/Magnum/Math/Angle.h +++ b/src/Magnum/Math/Angle.h @@ -98,8 +98,15 @@ These silent errors are easily avoided by requiring explicit conversions: */ template class Deg: public Unit { public: - /** @brief Construct zero angle */ - constexpr /*implicit*/ Deg(ZeroInitT = ZeroInit) noexcept + /** + * @brief Default constructor + * + * Equivalent to @ref Deg(ZeroInitT). + */ + constexpr /*implicit*/ Deg() noexcept: Unit{ZeroInit} {} + + /** @brief Construct a zero angle */ + constexpr explicit Deg(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Unit{ZeroInit} @@ -170,8 +177,15 @@ See @ref Deg for more information. */ template class Rad: public Unit { public: - /** @brief Default constructor */ - constexpr /*implicit*/ Rad(ZeroInitT = ZeroInit) noexcept + /** + * @brief Default constructor + * + * Equivalent to @ref Rad(ZeroInitT). + */ + constexpr /*implicit*/ Rad() noexcept: Unit{ZeroInit} {} + + /** @brief Constructor a zero angle */ + constexpr explicit Rad(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Unit{ZeroInit} diff --git a/src/Magnum/Math/Bezier.h b/src/Magnum/Math/Bezier.h index 42a639908..0706b0019 100644 --- a/src/Magnum/Math/Bezier.h +++ b/src/Magnum/Math/Bezier.h @@ -100,9 +100,16 @@ template class Bezier { /** * @brief Default constructor * - * Construct the curve with all control points being zero vectors. + * Equivalent to @ref Bezier(ZeroInitT). */ - constexpr /*implicit*/ Bezier(ZeroInitT = ZeroInit) noexcept + constexpr /*implicit*/ Bezier() noexcept: Bezier{typename Implementation::GenerateSequence::Type{}, ZeroInit} {} + + /** + * @brief Construct a zero curve + * + * All control points are zero vectors. + */ + constexpr explicit Bezier(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Bezier{typename Implementation::GenerateSequence::Type{}, ZeroInit} diff --git a/src/Magnum/Math/BoolVector.h b/src/Magnum/Math/BoolVector.h index b23cf5b0d..d415af1ad 100644 --- a/src/Magnum/Math/BoolVector.h +++ b/src/Magnum/Math/BoolVector.h @@ -95,8 +95,15 @@ template class BoolVector { DataSize = (size-1)/8+1 /**< Vector storage size */ }; + /** + * @brief Default constructor + * + * Equivalent to @ref BoolVector(ZeroInitT). + */ + constexpr /*implicit*/ BoolVector() noexcept: _data{} {} + /** @brief Construct zero-filled boolean vector */ - constexpr /*implicit*/ BoolVector(ZeroInitT = ZeroInit) noexcept: _data{} {} + constexpr explicit BoolVector(ZeroInitT) noexcept: _data{} {} /** @brief Construct without initializing the contents */ explicit BoolVector(NoInitT) noexcept {} diff --git a/src/Magnum/Math/Color.h b/src/Magnum/Math/Color.h index 34c46c80e..1b4e4c0ab 100644 --- a/src/Magnum/Math/Color.h +++ b/src/Magnum/Math/Color.h @@ -428,9 +428,16 @@ template class Color3: public Vector3 { /** * @brief Default constructor * + * Equivalent to @ref Color3(ZeroInitT). + */ + constexpr /*implicit*/ Color3() noexcept: Vector3{ZeroInit} {} + + /** + * @brief Construct a zero color + * * All components are set to zero. */ - constexpr /*implicit*/ Color3(ZeroInitT = ZeroInit) noexcept + constexpr explicit Color3(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Vector3{ZeroInit} @@ -833,11 +840,15 @@ class Color4: public Vector4 { /** * @brief Default constructor * - * All components are set to zero. + * Equivalent to @ref Color4(ZeroInitT). */ - constexpr /*implicit*/ Color4() noexcept: Vector4(T(0), T(0), T(0), T(0)) {} + constexpr /*implicit*/ Color4() noexcept: Vector4{ZeroInit} {} - /** @copydoc Vector::Vector(ZeroInitT) */ + /** + * @brief Construct a zero color + * + * All components are set to zero. + */ constexpr explicit Color4(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT @@ -1042,9 +1053,16 @@ template struct ColorHsv { /** * @brief Default constructor * + * Equivalent to @ref ColorHsv(ZeroInitT). + */ + constexpr /*implicit*/ ColorHsv() noexcept: hue{}, saturation{}, value{} {} + + /** + * @brief Construct a zero color + * * All members are set to zero. */ - constexpr /*implicit*/ ColorHsv(ZeroInitT = ZeroInit) noexcept: hue{}, saturation{}, value{} {} + constexpr explicit ColorHsv(ZeroInitT) noexcept: hue{}, saturation{}, value{} {} /** @brief Construct without initializing the contents */ explicit ColorHsv(NoInitT) noexcept: hue{NoInit} /* and the others not */ {} diff --git a/src/Magnum/Math/Complex.h b/src/Magnum/Math/Complex.h index 62a7469cd..7b2ae415c 100644 --- a/src/Magnum/Math/Complex.h +++ b/src/Magnum/Math/Complex.h @@ -124,11 +124,18 @@ template class Complex { /** * @brief Default constructor * + * Equivalent to @ref Complex(IdentityInitT). + */ + constexpr /*implicit*/ Complex() noexcept: _real(T(1)), _imaginary(T(0)) {} + + /** + * @brief Identity constructor + * * Constructs unit complex number. @f[ * c = 1 + i0 * @f] */ - constexpr /*implicit*/ Complex(IdentityInitT = IdentityInit) noexcept: _real(T(1)), _imaginary(T(0)) {} + constexpr explicit Complex(IdentityInitT) noexcept: _real(T(1)), _imaginary(T(0)) {} /** @brief Construct zero-initialized complex number */ constexpr explicit Complex(ZeroInitT) noexcept: _real{}, _imaginary{} {} diff --git a/src/Magnum/Math/Dual.h b/src/Magnum/Math/Dual.h index 8053a0241..6fd067acc 100644 --- a/src/Magnum/Math/Dual.h +++ b/src/Magnum/Math/Dual.h @@ -69,11 +69,11 @@ template class Dual { /** @brief Construct zero-initialized dual number */ #ifdef DOXYGEN_GENERATING_OUTPUT - constexpr /*implicit*/ Dual(ZeroInitT) noexcept; + constexpr explicit Dual(ZeroInitT) noexcept; #else /* MSVC 2015 can't handle {} instead of ::value */ - template::value>::type> constexpr /*implicit*/ Dual(ZeroInitT) noexcept: _real{}, _dual{} {} - template::value>::type> constexpr /*implicit*/ Dual(ZeroInitT) noexcept: _real{ZeroInit}, _dual{ZeroInit} {} + template::value>::type> constexpr explicit Dual(ZeroInitT) noexcept: _real{}, _dual{} {} + template::value>::type> constexpr explicit Dual(ZeroInitT) noexcept: _real{ZeroInit}, _dual{ZeroInit} {} #endif /** @brief Construct without initializing the contents */ diff --git a/src/Magnum/Math/DualComplex.h b/src/Magnum/Math/DualComplex.h index 4c0fc3a74..0f01d1022 100644 --- a/src/Magnum/Math/DualComplex.h +++ b/src/Magnum/Math/DualComplex.h @@ -105,14 +105,21 @@ template class DualComplex: public Dual> { /** * @brief Default constructor * + * Equivalent to @ref DualComplex(IdentityInitT). + */ + constexpr /*implicit*/ DualComplex() noexcept: Dual>({}, {T(0), T(0)}) {} + + /** + * @brief Identity constructor + * * Creates unit dual complex number. @f[ * \hat c = (0 + i1) + \epsilon (0 + i0) * @f] */ #ifdef DOXYGEN_GENERATING_OUTPUT - constexpr /*implicit*/ DualComplex(IdentityInitT = IdentityInit) noexcept; + constexpr explicit DualComplex(IdentityInitT) noexcept; #else - constexpr /*implicit*/ DualComplex(IdentityInitT = IdentityInit) noexcept: Dual>({}, {T(0), T(0)}) {} + constexpr explicit DualComplex(IdentityInitT) noexcept: Dual>({}, {T(0), T(0)}) {} #endif /** @brief Construct zero-initialized dual complex number */ diff --git a/src/Magnum/Math/DualQuaternion.h b/src/Magnum/Math/DualQuaternion.h index d66a6cb6e..ca3d7f806 100644 --- a/src/Magnum/Math/DualQuaternion.h +++ b/src/Magnum/Math/DualQuaternion.h @@ -245,11 +245,18 @@ template class DualQuaternion: public Dual> { /** * @brief Default constructor * + * Equivalent to @ref DualQuaternion(IdentityInitT). + */ + constexpr /*implicit*/ DualQuaternion() noexcept: Dual>{{}, {{}, T(0)}} {} + + /** + * @brief Identity constructor + * * Creates unit dual quaternion. @f[ * \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol 0, 0] * @f] */ - constexpr /*implicit*/ DualQuaternion(IdentityInitT = IdentityInit) noexcept + constexpr explicit DualQuaternion(IdentityInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Dual>{{}, {{}, T(0)}} diff --git a/src/Magnum/Math/Frustum.h b/src/Magnum/Math/Frustum.h index 7692aa355..51b731044 100644 --- a/src/Magnum/Math/Frustum.h +++ b/src/Magnum/Math/Frustum.h @@ -69,13 +69,20 @@ template class Frustum { m.row(3) - m.row(2)}; } + /** + * @brief Default constructor + * + * Equivalent to @ref Frustum(IdentityInitT). + */ + constexpr /*implicit*/ Frustum() noexcept: Frustum{IdentityInit} {} + /** * @brief Identity constructor * * Equivalent to creating a frustum from an identity matrix. * @see @ref fromMatrix() */ - constexpr /*implicit*/ Frustum(IdentityInitT = IdentityInit) noexcept; + constexpr explicit Frustum(IdentityInitT) noexcept; /** @brief Construct a frustum without initializing the contents */ explicit Frustum(NoInitT) noexcept: _data{Vector4{NoInit}, Vector4{NoInit}, Vector4{NoInit}, Vector4{NoInit}, Vector4{NoInit}, Vector4{NoInit}} {} diff --git a/src/Magnum/Math/Half.h b/src/Magnum/Math/Half.h index cf9b980ed..e12be91bc 100644 --- a/src/Magnum/Math/Half.h +++ b/src/Magnum/Math/Half.h @@ -64,9 +64,12 @@ class Half { /** * @brief Default constructor * - * Creates a zero value. + * Equivalent to @ref Half(ZeroInitT). */ - constexpr /*implicit*/ Half(ZeroInitT = ZeroInit) noexcept: _data{} {} + constexpr /*implicit*/ Half() noexcept: _data{} {} + + /** @brief Construct a zero value */ + constexpr explicit Half(ZeroInitT) noexcept: _data{} {} /** @brief Construct a half value from underlying 16-bit representation */ constexpr explicit Half(UnsignedShort data) noexcept: _data{data} {} diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 5a9d8681b..2e018b5bc 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -65,10 +65,17 @@ template class Matrix: public RectangularMatrix{typename Implementation::GenerateSequence::Type(), Vector(T(1))} {} + + /** + * @brief Identity constructor + * + * Creates an identity matrix. @p value allows you to specify value on * diagonal. */ - constexpr /*implicit*/ Matrix(IdentityInitT = IdentityInit, T value = T(1)) noexcept + constexpr explicit Matrix(IdentityInitT, T value = T(1)) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : RectangularMatrix{typename Implementation::GenerateSequence::Type(), Vector(value)} diff --git a/src/Magnum/Math/Matrix3.h b/src/Magnum/Math/Matrix3.h index e08691e37..cc45f31dc 100644 --- a/src/Magnum/Math/Matrix3.h +++ b/src/Magnum/Math/Matrix3.h @@ -198,10 +198,17 @@ template class Matrix3: public Matrix3x3 { /** * @brief Default constructor * - * Creates identity matrix. @p value allows you to specify value on + * Equivalent to @ref Matrix3(IdentityInitT, T). + */ + constexpr /*implicit*/ Matrix3() noexcept: Matrix3x3{IdentityInit, T(1)} {} + + /** + * @brief Identity constructor + * + * Creates an identity matrix. @p value allows you to specify value on * diagonal. */ - constexpr /*implicit*/ Matrix3(IdentityInitT = IdentityInit, T value = T{1}) noexcept + constexpr explicit Matrix3(IdentityInitT, T value = T{1}) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Matrix3x3{IdentityInit, value} diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index d7336b80c..878418477 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -383,10 +383,17 @@ template class Matrix4: public Matrix4x4 { /** * @brief Default constructor * - * Creates identity matrix. @p value allows you to specify value on + * Equivalent to @ref Matrix4(IdentityInitT, T). + */ + constexpr /*implicit*/ Matrix4() noexcept: Matrix4x4{IdentityInit, T(1)} {} + + /** + * @brief Identity constructor + * + * Creates an identity matrix. @p value allows you to specify value on * diagonal. */ - constexpr /*implicit*/ Matrix4(IdentityInitT = IdentityInit, T value = T{1}) noexcept + constexpr explicit Matrix4(IdentityInitT, T value = T{1}) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Matrix4x4{IdentityInit, value} diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 70f9aec79..c058bec15 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -270,11 +270,18 @@ template class Quaternion { /** * @brief Default constructor * + * Equivalent to @ref Quaternion(IdentityInitT). + */ + constexpr /*implicit*/ Quaternion() noexcept: _scalar{T(1)} {} + + /** + * @brief Identity constructor + * * Creates unit quaternion. @f[ * q = [\boldsymbol 0, 1] * @f] */ - constexpr /*implicit*/ Quaternion(IdentityInitT = IdentityInit) noexcept: _scalar{T(1)} {} + constexpr explicit Quaternion(IdentityInitT) noexcept: _scalar{T(1)} {} /** @brief Construct zero-initialized quaternion */ constexpr explicit Quaternion(ZeroInitT) noexcept: _vector{ZeroInit}, _scalar{T{0}} {} diff --git a/src/Magnum/Math/Range.h b/src/Magnum/Math/Range.h index 0509260e0..ad39fdae5 100644 --- a/src/Magnum/Math/Range.h +++ b/src/Magnum/Math/Range.h @@ -96,12 +96,19 @@ template class Range { return {center - halfSize, center + halfSize}; } + /** + * @brief Default constructor + * + * Equivalent to @ref Range(ZeroInitT). + */ + constexpr /*implicit*/ Range() noexcept: Range{ZeroInit, typename std::conditional::type{}} {} + /** * @brief Construct zero range * * Construct zero-size range positioned at origin. */ - constexpr /*implicit*/ Range(ZeroInitT = ZeroInit) noexcept: Range{ZeroInit, typename std::conditional::type{}} {} + constexpr explicit Range(ZeroInitT) noexcept: Range{ZeroInit, typename std::conditional::type{}} {} /** @brief Construct without initializing the contents */ explicit Range(NoInitT) noexcept: Range{NoInit, typename std::conditional::type{}} {} @@ -351,8 +358,15 @@ See @ref Range for more information. */ template class Range2D: public Range<2, T> { public: + /** + * @brief Default constructor + * + * Equivalent to @ref Range2D(ZeroInitT). + */ + constexpr /*implicit*/ Range2D() noexcept: Range<2, T>{ZeroInit} {} + /** @copydoc Range(ZeroInitT) */ - constexpr /*implicit*/ Range2D(ZeroInitT = ZeroInit) noexcept + constexpr explicit Range2D(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Range<2, T>{ZeroInit} @@ -494,8 +508,15 @@ See @ref Range for more information. */ template class Range3D: public Range<3, T> { public: + /** + * @brief Default constructor + * + * Equivalent to @ref Range3D(ZeroInitT). + */ + constexpr /*implicit*/ Range3D() noexcept: Range<3, T>{ZeroInit} {} + /** @copydoc Range(ZeroInitT) */ - constexpr /*implicit*/ Range3D(ZeroInitT = ZeroInit) noexcept + constexpr explicit Range3D(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Range<3, T>{ZeroInit} diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 5c3f1343f..24c2b794f 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -107,8 +107,15 @@ template class RectangularMatrix { return RectangularMatrix(typename Implementation::GenerateSequence::Type(), diagonal); } + /** + * @brief Default constructor + * + * Equivalent to @ref RectangularMatrix(ZeroInitT). + */ + constexpr /*implicit*/ RectangularMatrix() noexcept: RectangularMatrix{typename Implementation::GenerateSequence::Type{}, ZeroInit} {} + /** @brief Construct zero-filled matrix */ - constexpr /*implicit*/ RectangularMatrix(ZeroInitT = ZeroInit) noexcept + constexpr explicit RectangularMatrix(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : RectangularMatrix{typename Implementation::GenerateSequence::Type{}, ZeroInit} diff --git a/src/Magnum/Math/Test/AngleTest.cpp b/src/Magnum/Math/Test/AngleTest.cpp index 7c7aabb2d..69dc9fe2c 100644 --- a/src/Magnum/Math/Test/AngleTest.cpp +++ b/src/Magnum/Math/Test/AngleTest.cpp @@ -170,6 +170,10 @@ void AngleTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); } void AngleTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index 97159ac44..cadf20d52 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -132,6 +132,9 @@ void BezierTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void BezierTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp index bb5ba29c1..f67ba47db 100644 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ b/src/Magnum/Math/Test/BoolVectorTest.cpp @@ -129,6 +129,9 @@ void BoolVectorTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void BoolVectorTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/ColorTest.cpp b/src/Magnum/Math/Test/ColorTest.cpp index 24b2aeb57..0932b12e0 100644 --- a/src/Magnum/Math/Test/ColorTest.cpp +++ b/src/Magnum/Math/Test/ColorTest.cpp @@ -290,12 +290,12 @@ void ColorTest::construct() { void ColorTest::constructDefault() { constexpr Color3 a1; - constexpr Color3 a2{Math::ZeroInit}; + constexpr Color3 a2{ZeroInit}; CORRADE_COMPARE(a1, Color3(0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(a2, Color3(0.0f, 0.0f, 0.0f)); constexpr Color4 b1; - constexpr Color4 b2{Math::ZeroInit}; + constexpr Color4 b2{ZeroInit}; CORRADE_COMPARE(b1, Color4(0.0f, 0.0f, 0.0f, 0.0f)); CORRADE_COMPARE(b2, Color4(0.0f, 0.0f, 0.0f, 0.0f)); @@ -306,13 +306,17 @@ void ColorTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); } void ColorTest::constructNoInit() { Color3 a{1.0f, 0.5f, 0.75f}; Color4 b{1.0f, 0.5f, 0.75f, 0.5f}; - new(&a) Color3{Math::NoInit}; - new(&b) Color4{Math::NoInit}; + new(&a) Color3{NoInit}; + new(&b) Color4{NoInit}; { #if defined(__GNUC__) && __GNUC__*100 + __GNUC_MINOR__ >= 601 && __OPTIMIZE__ CORRADE_EXPECT_FAIL("GCC 6.1+ misoptimizes and overwrites the value."); @@ -481,6 +485,9 @@ void ColorTest::constructHsvDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void ColorTest::constructHsvNoInit() { diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index 18d3736b9..76353782a 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -185,6 +185,9 @@ void ComplexTest::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void ComplexTest::constructZero() { @@ -192,6 +195,9 @@ void ComplexTest::constructZero() { CORRADE_COMPARE(a, Complex(0.0f, 0.0f)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void ComplexTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/CubicHermiteTest.cpp b/src/Magnum/Math/Test/CubicHermiteTest.cpp index 948781acd..8fbba021f 100644 --- a/src/Magnum/Math/Test/CubicHermiteTest.cpp +++ b/src/Magnum/Math/Test/CubicHermiteTest.cpp @@ -339,6 +339,9 @@ void CubicHermiteTest::constructZeroScalar() { CORRADE_COMPARE(b, (CubicHermite1D{0.0f, 0.0f, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void CubicHermiteTest::constructZeroVector() { @@ -349,6 +352,9 @@ void CubicHermiteTest::constructZeroVector() { CORRADE_COMPARE(b, (CubicHermite2D{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void CubicHermiteTest::constructZeroComplex() { @@ -359,6 +365,9 @@ void CubicHermiteTest::constructZeroComplex() { CORRADE_COMPARE(b, (CubicHermiteComplex{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void CubicHermiteTest::constructZeroQuaternion() { @@ -375,6 +384,9 @@ void CubicHermiteTest::constructZeroQuaternion() { {{0.0f, 0.0f, 0.0f}, 0.0f}})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void CubicHermiteTest::constructIdentityScalar() { @@ -393,6 +405,9 @@ void CubicHermiteTest::constructIdentityComplex() { CORRADE_COMPARE(b, (CubicHermiteComplex{{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void CubicHermiteTest::constructIdentityQuaternion() { @@ -409,6 +424,9 @@ void CubicHermiteTest::constructIdentityQuaternion() { {{0.0f, 0.0f, 0.0f}, 0.0f}})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void CubicHermiteTest::constructNoInitScalar() { diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index bc55b6ec4..3c58b61ae 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -176,6 +176,9 @@ void DualComplexTest::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void DualComplexTest::constructZero() { @@ -183,6 +186,9 @@ void DualComplexTest::constructZero() { CORRADE_COMPARE(a, DualComplex({0.0f, 0.0f}, {0.0f, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void DualComplexTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 26aa5db54..4d92ce739 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -201,6 +201,9 @@ void DualQuaternionTest::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void DualQuaternionTest::constructZero() { @@ -208,6 +211,9 @@ void DualQuaternionTest::constructZero() { CORRADE_COMPARE(a, DualQuaternion({{0.0f, 0.0f, 0.0f}, 0.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void DualQuaternionTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index f01cd7314..8c560d5df 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -138,6 +138,10 @@ void DualTest::constructZero() { CORRADE_VERIFY((std::is_nothrow_constructible::value)); CORRADE_VERIFY((std::is_nothrow_constructible>, ZeroInitT>::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible>>::value)); } void DualTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/FrustumTest.cpp b/src/Magnum/Math/Test/FrustumTest.cpp index f6a33c911..f0b7f3f88 100644 --- a/src/Magnum/Math/Test/FrustumTest.cpp +++ b/src/Magnum/Math/Test/FrustumTest.cpp @@ -150,6 +150,9 @@ void FrustumTest::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void FrustumTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/HalfTest.cpp b/src/Magnum/Math/Test/HalfTest.cpp index e9b551a2e..a19550862 100644 --- a/src/Magnum/Math/Test/HalfTest.cpp +++ b/src/Magnum/Math/Test/HalfTest.cpp @@ -564,6 +564,9 @@ void HalfTest::constructDefault() { CORRADE_VERIFY((std::is_nothrow_default_constructible::value)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void HalfTest::constructValue() { diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index e5dcfad79..a0245e0a3 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -184,6 +184,9 @@ void Matrix3Test::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Matrix3Test::constructZero() { @@ -193,6 +196,9 @@ void Matrix3Test::constructZero() { {0.0f, 0.0f, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Matrix3Test::constructNoInit() { diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 09896995c..c80b956e7 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -217,6 +217,9 @@ void Matrix4Test::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Matrix4Test::constructZero() { @@ -227,6 +230,9 @@ void Matrix4Test::constructZero() { {0.0f, 0.0f, 0.0f, 0.0f})); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Matrix4Test::constructNoInit() { diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index e127612bd..ed92e2e4b 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -161,6 +161,9 @@ void MatrixTest::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void MatrixTest::constructZero() { @@ -171,6 +174,9 @@ void MatrixTest::constructZero() { Vector4(0.0f, 0.0f, 0.0f, 0.0f))); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void MatrixTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index 5c7d408aa..bf989c7f5 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -211,6 +211,9 @@ void QuaternionTest::constructIdentity() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void QuaternionTest::constructZero() { @@ -218,6 +221,9 @@ void QuaternionTest::constructZero() { CORRADE_COMPARE(a, Quaternion({0.0f, 0.0f, 0.0f}, 0.0f)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void QuaternionTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index 3bb6951b3..99b9e0f66 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -231,6 +231,11 @@ void RangeTest::constructDefault() { CORRADE_VERIFY((std::is_nothrow_constructible::value)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); } void RangeTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 8e6964127..f31bf0314 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -174,6 +174,9 @@ void RectangularMatrixTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void RectangularMatrixTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/UnitTest.cpp b/src/Magnum/Math/Test/UnitTest.cpp index b6a657c43..73256de92 100644 --- a/src/Magnum/Math/Test/UnitTest.cpp +++ b/src/Magnum/Math/Test/UnitTest.cpp @@ -87,6 +87,9 @@ void UnitTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void UnitTest::constructNoInit() { diff --git a/src/Magnum/Math/Test/Vector2Test.cpp b/src/Magnum/Math/Test/Vector2Test.cpp index 0ddb66c1c..e54146b32 100644 --- a/src/Magnum/Math/Test/Vector2Test.cpp +++ b/src/Magnum/Math/Test/Vector2Test.cpp @@ -117,6 +117,9 @@ void Vector2Test::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Vector2Test::constructNoInit() { diff --git a/src/Magnum/Math/Test/Vector3Test.cpp b/src/Magnum/Math/Test/Vector3Test.cpp index 7f6050887..40a5411d1 100644 --- a/src/Magnum/Math/Test/Vector3Test.cpp +++ b/src/Magnum/Math/Test/Vector3Test.cpp @@ -117,6 +117,9 @@ void Vector3Test::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Vector3Test::constructNoInit() { diff --git a/src/Magnum/Math/Test/Vector4Test.cpp b/src/Magnum/Math/Test/Vector4Test.cpp index e78f3f5b2..229c5bea7 100644 --- a/src/Magnum/Math/Test/Vector4Test.cpp +++ b/src/Magnum/Math/Test/Vector4Test.cpp @@ -138,6 +138,9 @@ void Vector4Test::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void Vector4Test::constructNoInit() { diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 6c6ba3389..76a626d36 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -210,6 +210,9 @@ void VectorTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY((std::is_nothrow_constructible::value)); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!(std::is_convertible::value)); } void VectorTest::constructNoInit() { diff --git a/src/Magnum/Math/Unit.h b/src/Magnum/Math/Unit.h index a7597a531..d6fdcaa0d 100644 --- a/src/Magnum/Math/Unit.h +++ b/src/Magnum/Math/Unit.h @@ -46,8 +46,15 @@ template class Derived, class T> class Unit { public: typedef T Type; /**< @brief Underlying data type */ + /** + * @brief Default constructor + * + * Equivalent to @ref Unit(ZeroInitT). + */ + constexpr /*implicit*/ Unit() noexcept: _value(T(0)) {} + /** @brief Construct zero value */ - constexpr /*implicit*/ Unit(ZeroInitT = ZeroInit) noexcept: _value(T(0)) {} + constexpr explicit Unit(ZeroInitT) noexcept: _value(T(0)) {} /** @brief Construct without initializing the contents */ explicit Unit(NoInitT) noexcept {} diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 2015cf31c..dccb41d4c 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -165,11 +165,18 @@ template class Vector { /** * @brief Default constructor * + * Equivalent to @ref Vector(ZeroInitT). + */ + constexpr /*implicit*/ Vector() noexcept: _data{} {} + + /** + * @brief Construct a zero vector + * * @f[ * \boldsymbol v = \boldsymbol 0 * @f] */ - constexpr /*implicit*/ Vector(ZeroInitT = ZeroInit) noexcept: _data{} {} + constexpr explicit Vector(ZeroInitT) noexcept: _data{} {} /** @brief Construct vector without initializing the contents */ explicit Vector(NoInitT) noexcept {} diff --git a/src/Magnum/Math/Vector2.h b/src/Magnum/Math/Vector2.h index cf30409f2..05a0def50 100644 --- a/src/Magnum/Math/Vector2.h +++ b/src/Magnum/Math/Vector2.h @@ -100,8 +100,15 @@ template class Vector2: public Vector<2, T> { */ constexpr static Vector2 yScale(T scale) { return {T(1), scale}; } + /** + * @brief Default constructor + * + * Equivalent to @ref Vector2(ZeroInitT). + */ + constexpr /*implicit*/ Vector2() noexcept: Vector<2, T>{ZeroInit} {} + /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr /*implicit*/ Vector2(ZeroInitT = ZeroInit) noexcept + constexpr explicit Vector2(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Vector<2, T>{ZeroInit} diff --git a/src/Magnum/Math/Vector3.h b/src/Magnum/Math/Vector3.h index 88ef8d5ba..d1d720850 100644 --- a/src/Magnum/Math/Vector3.h +++ b/src/Magnum/Math/Vector3.h @@ -121,8 +121,15 @@ template class Vector3: public Vector<3, T> { */ constexpr static Vector3 zScale(T scale) { return {T(1), T(1), scale}; } + /** + * @brief Default constructor + * + * Equivalent to @ref Vector3(ZeroInitT). + */ + constexpr /*implicit*/ Vector3() noexcept: Vector<3, T>{ZeroInit} {} + /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr /*implicit*/ Vector3(ZeroInitT = ZeroInit) noexcept + constexpr explicit Vector3(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Vector<3, T>{ZeroInit} diff --git a/src/Magnum/Math/Vector4.h b/src/Magnum/Math/Vector4.h index b10cb16ff..7e7f113d7 100644 --- a/src/Magnum/Math/Vector4.h +++ b/src/Magnum/Math/Vector4.h @@ -59,8 +59,15 @@ template class Vector4: public Vector<4, T> { 3 < otherSize ? a[3] : w}; } + /** + * @brief Default constructor + * + * Equivalent to @ref Vector4(ZeroInitT). + */ + constexpr /*implicit*/ Vector4() noexcept: Vector<4, T>{ZeroInit} {} + /** @copydoc Vector::Vector(ZeroInitT) */ - constexpr /*implicit*/ Vector4(ZeroInitT = ZeroInit) noexcept + constexpr explicit Vector4(ZeroInitT) noexcept /** @todoc remove workaround when doxygen is sane */ #ifndef DOXYGEN_GENERATING_OUTPUT : Vector<4, T>{ZeroInit}