Use explicit conversion operator instead of explicit constructor

I also added a type trait test to check whether the conversion operator is marked explicit.

this change has the advantage of being  clearer imo as it is a conversion operator for conersions not a constructor.

and also it allows users to take the address of convesion operator which I don't know if someone might find that useful.
This commit is contained in:
ZXShady 2024-09-29 23:18:48 +01:00 committed by Lukas Dürrenberger
parent 4e77e3ee95
commit de9286c11f
11 changed files with 41 additions and 55 deletions

View File

@ -128,18 +128,13 @@ struct Vector4
#endif #endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Conversion constructor /// \brief Converts the vector to another type of vector
///
/// \param other 4D vector of different type
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename U> template <typename U>
constexpr explicit Vector4(const Vector4<U>& other) : constexpr explicit operator Vector4<U>() const
x(static_cast<T>(other.x)),
y(static_cast<T>(other.y)),
z(static_cast<T>(other.z)),
w(static_cast<T>(other.w))
{ {
return Vector4<U>(static_cast<U>(x), static_cast<U>(y), static_cast<U>(z), static_cast<U>(w));
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -64,18 +64,11 @@ public:
constexpr Rect(Vector2<T> position, Vector2<T> size); constexpr Rect(Vector2<T> position, Vector2<T> size);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the rectangle from another type of rectangle /// \brief Converts the rectangle to another type of rectangle
///
/// This constructor doesn't replace the copy constructor,
/// it's called only when U != T.
/// A call to this constructor will fail to compile if U
/// is not convertible to T.
///
/// \param rectangle Rectangle to convert
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename U> template <typename U>
constexpr explicit Rect(const Rect<U>& rectangle); constexpr explicit operator Rect<U>() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check if a point is inside the rectangle's area /// \brief Check if a point is inside the rectangle's area

View File

@ -40,8 +40,9 @@ constexpr Rect<T>::Rect(Vector2<T> thePosition, Vector2<T> theSize) : position(t
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
template <typename U> template <typename U>
constexpr Rect<T>::Rect(const Rect<U>& rectangle) : position(rectangle.position), size(rectangle.size) constexpr Rect<T>::operator Rect<U>() const
{ {
return Rect<U>(Vector2<U>(position), Vector2<U>(size));
} }

View File

@ -58,18 +58,11 @@ public:
constexpr Vector2(T x, T y); constexpr Vector2(T x, T y);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the vector from another type of vector /// \brief Converts the vector to another type of vector
///
/// This constructor doesn't replace the copy constructor,
/// it's called only when U != T.
/// A call to this constructor will fail to compile if U
/// is not convertible to T.
///
/// \param vector Vector to convert
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename U> template <typename U>
constexpr explicit Vector2(Vector2<U> vector); constexpr explicit operator Vector2<U>() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the vector from polar coordinates <i><b>(floating-point)</b></i> /// \brief Construct the vector from polar coordinates <i><b>(floating-point)</b></i>

View File

@ -49,8 +49,9 @@ constexpr Vector2<T>::Vector2(T x, T y) : x(x), y(y)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
template <typename U> template <typename U>
constexpr Vector2<T>::Vector2(Vector2<U> vector) : x(static_cast<T>(vector.x)), y(static_cast<T>(vector.y)) constexpr Vector2<T>::operator Vector2<U>() const
{ {
return Vector2<U>(static_cast<U>(x), static_cast<U>(y));
} }

View File

@ -57,18 +57,11 @@ public:
constexpr Vector3(T x, T y, T z); constexpr Vector3(T x, T y, T z);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the vector from another type of vector /// \brief Converts the vector to another type of vector
///
/// This constructor doesn't replace the copy constructor,
/// it's called only when U != T.
/// A call to this constructor will fail to compile if U
/// is not convertible to T.
///
/// \param vector Vector to convert
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename U> template <typename U>
constexpr explicit Vector3(const Vector3<U>& vector); constexpr explicit operator Vector3<U>() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Length of the vector <i><b>(floating-point)</b></i>. /// \brief Length of the vector <i><b>(floating-point)</b></i>.

View File

@ -49,11 +49,9 @@ constexpr Vector3<T>::Vector3(T x, T y, T z) : x(x), y(y), z(z)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
template <typename U> template <typename U>
constexpr Vector3<T>::Vector3(const Vector3<U>& vector) : constexpr Vector3<T>::operator Vector3<U>() const
x(static_cast<T>(vector.x)),
y(static_cast<T>(vector.y)),
z(static_cast<T>(vector.z))
{ {
return Vector3<U>(static_cast<U>(x), static_cast<U>(y), static_cast<U>(z));
} }

View File

@ -133,8 +133,10 @@ TEST_CASE("[Graphics] sf::Glsl")
STATIC_CHECK(vec.w == 4); STATIC_CHECK(vec.w == 4);
} }
SECTION("Conversion constructor") SECTION("Conversion operator")
{ {
STATIC_CHECK(!std::is_convertible_v<sf::Glsl::Ivec4, sf::Glsl::Vec4>);
constexpr sf::Glsl::Ivec4 ivec(10, 12, 14, 16); constexpr sf::Glsl::Ivec4 ivec(10, 12, 14, 16);
constexpr sf::Glsl::Vec4 vec(ivec); constexpr sf::Glsl::Vec4 vec(ivec);
STATIC_CHECK(vec.x == 10); STATIC_CHECK(vec.x == 10);
@ -181,8 +183,10 @@ TEST_CASE("[Graphics] sf::Glsl")
STATIC_CHECK(vec.w == 4); STATIC_CHECK(vec.w == 4);
} }
SECTION("Conversion constructor") SECTION("Conversion operator")
{ {
STATIC_CHECK(!std::is_convertible_v<sf::Glsl::Bvec4, sf::Glsl::Ivec4>);
constexpr sf::Glsl::Bvec4 bvec(true, false, true, false); constexpr sf::Glsl::Bvec4 bvec(true, false, true, false);
constexpr sf::Glsl::Ivec4 vec(bvec); constexpr sf::Glsl::Ivec4 vec(bvec);
STATIC_CHECK(vec.x == 1); STATIC_CHECK(vec.x == 1);
@ -229,8 +233,10 @@ TEST_CASE("[Graphics] sf::Glsl")
STATIC_CHECK(vec.w == false); STATIC_CHECK(vec.w == false);
} }
SECTION("Conversion constructor") SECTION("Conversion operator")
{ {
STATIC_CHECK(!std::is_convertible_v<sf::Glsl::Ivec4, sf::Glsl::Bvec4>);
constexpr sf::Glsl::Ivec4 ivec(0, -7, 2, 10); constexpr sf::Glsl::Ivec4 ivec(0, -7, 2, 10);
constexpr sf::Glsl::Bvec4 vec(ivec); constexpr sf::Glsl::Bvec4 vec(ivec);
STATIC_CHECK(vec.x == false); STATIC_CHECK(vec.x == false);

View File

@ -35,15 +35,6 @@ TEMPLATE_TEST_CASE("[Graphics] sf::Rect", "", int, float)
STATIC_CHECK(rectangle.position == position); STATIC_CHECK(rectangle.position == position);
STATIC_CHECK(rectangle.size == dimension); STATIC_CHECK(rectangle.size == dimension);
} }
SECTION("Conversion constructor")
{
constexpr sf::FloatRect sourceRectangle({1.0f, 2.0f}, {3.0f, 4.0f});
constexpr sf::IntRect rectangle(sourceRectangle);
STATIC_CHECK(rectangle.position == sf::Vector2i(1, 2));
STATIC_CHECK(rectangle.size == sf::Vector2i(3, 4));
}
} }
SECTION("contains(Vector2)") SECTION("contains(Vector2)")
@ -81,6 +72,17 @@ TEMPLATE_TEST_CASE("[Graphics] sf::Rect", "", int, float)
SECTION("Operators") SECTION("Operators")
{ {
SECTION("operator Rect<U>")
{
STATIC_CHECK(!std::is_convertible_v<sf::FloatRect, sf::IntRect>);
constexpr sf::FloatRect sourceRectangle({1.0f, 2.0f}, {3.0f, 4.0f});
constexpr sf::IntRect rectangle(sourceRectangle);
STATIC_CHECK(rectangle.position == sf::Vector2i(1, 2));
STATIC_CHECK(rectangle.size == sf::Vector2i(3, 4));
}
SECTION("operator==") SECTION("operator==")
{ {
STATIC_CHECK(sf::Rect<TestType>() == sf::Rect<TestType>()); STATIC_CHECK(sf::Rect<TestType>() == sf::Rect<TestType>());

View File

@ -36,8 +36,10 @@ TEMPLATE_TEST_CASE("[System] sf::Vector2", "", int, float)
STATIC_CHECK(vector.y == 2); STATIC_CHECK(vector.y == 2);
} }
SECTION("Conversion constructor") SECTION("Conversion operator")
{ {
STATIC_CHECK(!std::is_convertible_v<sf::Vector2f, sf::Vector2i>);
constexpr sf::Vector2f sourceVector(1.0f, 2.0f); constexpr sf::Vector2f sourceVector(1.0f, 2.0f);
constexpr sf::Vector2i vector(sourceVector); constexpr sf::Vector2i vector(sourceVector);

View File

@ -33,8 +33,10 @@ TEMPLATE_TEST_CASE("[System] sf::Vector3", "", int, float)
STATIC_CHECK(vector.z == 3); STATIC_CHECK(vector.z == 3);
} }
SECTION("Conversion constructor") SECTION("Conversion operator")
{ {
STATIC_CHECK(!std::is_convertible_v<sf::Vector3f, sf::Vector3i>);
constexpr sf::Vector3f sourceVector(1.0f, 2.0f, 3.0f); constexpr sf::Vector3f sourceVector(1.0f, 2.0f, 3.0f);
constexpr sf::Vector3i vector(sourceVector); constexpr sf::Vector3i vector(sourceVector);