Make 'Rect' a 'constexpr' class

This commit is contained in:
Vittorio Romeo 2021-12-17 07:36:50 +01:00
parent f6bd12c300
commit cfeb7651b5
6 changed files with 63 additions and 47 deletions

View File

@ -32,6 +32,7 @@
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp> #include <SFML/System/Vector3.hpp>
#include <cstddef>
namespace sf namespace sf

View File

@ -29,7 +29,6 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <algorithm>
namespace sf namespace sf
@ -50,7 +49,7 @@ public:
/// Rect(0, 0, 0, 0)). /// Rect(0, 0, 0, 0)).
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Rect(); constexpr Rect();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the rectangle from its coordinates /// \brief Construct the rectangle from its coordinates
@ -64,7 +63,7 @@ public:
/// \param rectHeight Height of the rectangle /// \param rectHeight Height of the rectangle
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight); constexpr Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the rectangle from position and size /// \brief Construct the rectangle from position and size
@ -76,7 +75,7 @@ public:
/// \param size Size of the rectangle /// \param size Size of the rectangle
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Rect(const Vector2<T>& position, const Vector2<T>& size); constexpr Rect(const Vector2<T>& position, const Vector2<T>& size);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Construct the rectangle from another type of rectangle /// \brief Construct the rectangle from another type of rectangle
@ -90,7 +89,7 @@ public:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename U> template <typename U>
explicit Rect(const Rect<U>& rectangle); constexpr explicit Rect(const Rect<U>& rectangle);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check if a point is inside the rectangle's area /// \brief Check if a point is inside the rectangle's area
@ -106,7 +105,7 @@ public:
/// \see intersects /// \see intersects
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool contains(T x, T y) const; constexpr bool contains(T x, T y) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check if a point is inside the rectangle's area /// \brief Check if a point is inside the rectangle's area
@ -121,7 +120,7 @@ public:
/// \see intersects /// \see intersects
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool contains(const Vector2<T>& point) const; constexpr bool contains(const Vector2<T>& point) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check the intersection between two rectangles /// \brief Check the intersection between two rectangles
@ -133,7 +132,7 @@ public:
/// \see contains /// \see contains
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool intersects(const Rect<T>& rectangle) const; constexpr bool intersects(const Rect<T>& rectangle) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Check the intersection between two rectangles /// \brief Check the intersection between two rectangles
@ -149,7 +148,7 @@ public:
/// \see contains /// \see contains
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool intersects(const Rect<T>& rectangle, Rect<T>& intersection) const; constexpr bool intersects(const Rect<T>& rectangle, Rect<T>& intersection) const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get the position of the rectangle's top-left corner /// \brief Get the position of the rectangle's top-left corner
@ -159,7 +158,7 @@ public:
/// \see getSize /// \see getSize
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf::Vector2<T> getPosition() const; constexpr Vector2<T> getPosition() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Get the size of the rectangle /// \brief Get the size of the rectangle
@ -169,7 +168,7 @@ public:
/// \see getPosition /// \see getPosition
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
sf::Vector2<T> getSize() const; constexpr Vector2<T> getSize() const;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
@ -193,7 +192,7 @@ public:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool operator ==(const Rect<T>& left, const Rect<T>& right); [[nodiscard]] constexpr bool operator ==(const Rect<T>& left, const Rect<T>& right);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \relates Rect /// \relates Rect
@ -208,7 +207,7 @@ bool operator ==(const Rect<T>& left, const Rect<T>& right);
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool operator !=(const Rect<T>& left, const Rect<T>& right); [[nodiscard]] constexpr bool operator !=(const Rect<T>& left, const Rect<T>& right);
#include <SFML/Graphics/Rect.inl> #include <SFML/Graphics/Rect.inl>

View File

@ -25,7 +25,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
Rect<T>::Rect() : constexpr Rect<T>::Rect() :
left (0), left (0),
top (0), top (0),
width (0), width (0),
@ -37,7 +37,7 @@ height(0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
Rect<T>::Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight) : constexpr Rect<T>::Rect(T rectLeft, T rectTop, T rectWidth, T rectHeight) :
left (rectLeft), left (rectLeft),
top (rectTop), top (rectTop),
width (rectWidth), width (rectWidth),
@ -49,7 +49,7 @@ height(rectHeight)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
Rect<T>::Rect(const Vector2<T>& position, const Vector2<T>& size) : constexpr Rect<T>::Rect(const Vector2<T>& position, const Vector2<T>& size) :
left (position.x), left (position.x),
top (position.y), top (position.y),
width (size.x), width (size.x),
@ -62,7 +62,7 @@ height(size.y)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
template <typename U> template <typename U>
Rect<T>::Rect(const Rect<U>& rectangle) : constexpr Rect<T>::Rect(const Rect<U>& rectangle) :
left (static_cast<T>(rectangle.left)), left (static_cast<T>(rectangle.left)),
top (static_cast<T>(rectangle.top)), top (static_cast<T>(rectangle.top)),
width (static_cast<T>(rectangle.width)), width (static_cast<T>(rectangle.width)),
@ -73,15 +73,19 @@ height(static_cast<T>(rectangle.height))
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool Rect<T>::contains(T x, T y) const constexpr bool Rect<T>::contains(T x, T y) const
{ {
// Not using 'std::min' and 'std::max' to avoid depending on '<algorithm>'
const auto min = [](T a, T b){ return (a < b) ? a : b; };
const auto max = [](T a, T b){ return (a < b) ? b : a; };
// Rectangles with negative dimensions are allowed, so we must handle them correctly // Rectangles with negative dimensions are allowed, so we must handle them correctly
// Compute the real min and max of the rectangle on both axes // Compute the real min and max of the rectangle on both axes
T minX = std::min(left, static_cast<T>(left + width)); const T minX = min(left, static_cast<T>(left + width));
T maxX = std::max(left, static_cast<T>(left + width)); const T maxX = max(left, static_cast<T>(left + width));
T minY = std::min(top, static_cast<T>(top + height)); const T minY = min(top, static_cast<T>(top + height));
T maxY = std::max(top, static_cast<T>(top + height)); const T maxY = max(top, static_cast<T>(top + height));
return (x >= minX) && (x < maxX) && (y >= minY) && (y < maxY); return (x >= minX) && (x < maxX) && (y >= minY) && (y < maxY);
} }
@ -89,7 +93,7 @@ bool Rect<T>::contains(T x, T y) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool Rect<T>::contains(const Vector2<T>& point) const constexpr bool Rect<T>::contains(const Vector2<T>& point) const
{ {
return contains(point.x, point.y); return contains(point.x, point.y);
} }
@ -97,7 +101,7 @@ bool Rect<T>::contains(const Vector2<T>& point) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool Rect<T>::intersects(const Rect<T>& rectangle) const constexpr bool Rect<T>::intersects(const Rect<T>& rectangle) const
{ {
Rect<T> intersection; Rect<T> intersection;
return intersects(rectangle, intersection); return intersects(rectangle, intersection);
@ -106,27 +110,31 @@ bool Rect<T>::intersects(const Rect<T>& rectangle) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
bool Rect<T>::intersects(const Rect<T>& rectangle, Rect<T>& intersection) const constexpr bool Rect<T>::intersects(const Rect<T>& rectangle, Rect<T>& intersection) const
{ {
// Not using 'std::min' and 'std::max' to avoid depending on '<algorithm>'
const auto min = [](T a, T b){ return (a < b) ? a : b; };
const auto max = [](T a, T b){ return (a < b) ? b : a; };
// Rectangles with negative dimensions are allowed, so we must handle them correctly // Rectangles with negative dimensions are allowed, so we must handle them correctly
// Compute the min and max of the first rectangle on both axes // Compute the min and max of the first rectangle on both axes
T r1MinX = std::min(left, static_cast<T>(left + width)); const T r1MinX = min(left, static_cast<T>(left + width));
T r1MaxX = std::max(left, static_cast<T>(left + width)); const T r1MaxX = max(left, static_cast<T>(left + width));
T r1MinY = std::min(top, static_cast<T>(top + height)); const T r1MinY = min(top, static_cast<T>(top + height));
T r1MaxY = std::max(top, static_cast<T>(top + height)); const T r1MaxY = max(top, static_cast<T>(top + height));
// Compute the min and max of the second rectangle on both axes // Compute the min and max of the second rectangle on both axes
T r2MinX = std::min(rectangle.left, static_cast<T>(rectangle.left + rectangle.width)); const T r2MinX = min(rectangle.left, static_cast<T>(rectangle.left + rectangle.width));
T r2MaxX = std::max(rectangle.left, static_cast<T>(rectangle.left + rectangle.width)); const T r2MaxX = max(rectangle.left, static_cast<T>(rectangle.left + rectangle.width));
T r2MinY = std::min(rectangle.top, static_cast<T>(rectangle.top + rectangle.height)); const T r2MinY = min(rectangle.top, static_cast<T>(rectangle.top + rectangle.height));
T r2MaxY = std::max(rectangle.top, static_cast<T>(rectangle.top + rectangle.height)); const T r2MaxY = max(rectangle.top, static_cast<T>(rectangle.top + rectangle.height));
// Compute the intersection boundaries // Compute the intersection boundaries
T interLeft = std::max(r1MinX, r2MinX); const T interLeft = max(r1MinX, r2MinX);
T interTop = std::max(r1MinY, r2MinY); const T interTop = max(r1MinY, r2MinY);
T interRight = std::min(r1MaxX, r2MaxX); const T interRight = min(r1MaxX, r2MaxX);
T interBottom = std::min(r1MaxY, r2MaxY); const T interBottom = min(r1MaxY, r2MaxY);
// If the intersection is valid (positive non zero area), then there is an intersection // If the intersection is valid (positive non zero area), then there is an intersection
if ((interLeft < interRight) && (interTop < interBottom)) if ((interLeft < interRight) && (interTop < interBottom))
@ -141,22 +149,26 @@ bool Rect<T>::intersects(const Rect<T>& rectangle, Rect<T>& intersection) const
} }
} }
template <typename T>
sf::Vector2<T> Rect<T>::getPosition() const
{
return sf::Vector2<T>(left, top);
}
////////////////////////////////////////////////////////////
template <typename T> template <typename T>
sf::Vector2<T> Rect<T>::getSize() const constexpr Vector2<T> Rect<T>::getPosition() const
{ {
return sf::Vector2<T>(width, height); return Vector2<T>(left, top);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
inline bool operator ==(const Rect<T>& left, const Rect<T>& right) constexpr Vector2<T> Rect<T>::getSize() const
{
return Vector2<T>(width, height);
}
////////////////////////////////////////////////////////////
template <typename T>
constexpr bool operator ==(const Rect<T>& left, const Rect<T>& right)
{ {
return (left.left == right.left) && (left.width == right.width) && return (left.left == right.left) && (left.width == right.width) &&
(left.top == right.top) && (left.height == right.height); (left.top == right.top) && (left.height == right.height);
@ -165,7 +177,7 @@ inline bool operator ==(const Rect<T>& left, const Rect<T>& right)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
template <typename T> template <typename T>
inline bool operator !=(const Rect<T>& left, const Rect<T>& right) constexpr bool operator !=(const Rect<T>& left, const Rect<T>& right)
{ {
return !(left == right); return !(left == right);
} }

View File

@ -37,6 +37,7 @@
#include <SFML/Graphics/RenderStates.hpp> #include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/PrimitiveType.hpp> #include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Vertex.hpp> #include <SFML/Graphics/Vertex.hpp>
#include <cstddef>
namespace sf namespace sf

View File

@ -32,6 +32,7 @@
#include <SFML/Graphics/PrimitiveType.hpp> #include <SFML/Graphics/PrimitiveType.hpp>
#include <SFML/Graphics/Drawable.hpp> #include <SFML/Graphics/Drawable.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <cstddef>
namespace sf namespace sf

View File

@ -30,8 +30,10 @@
#include <SFML/Graphics/Vertex.hpp> #include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <cstring>
#include <mutex> #include <mutex>
#include <utility>
#include <cstddef>
#include <cstring>
namespace namespace
{ {