mirror of
https://github.com/SFML/SFML.git
synced 2025-01-31 13:45:13 +08:00
Transform Event::visit signature to accept multiple handlers
This commit is contained in:
parent
18393ea5cb
commit
d64a222c86
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
|
||||||
@ -339,26 +340,26 @@ public:
|
|||||||
[[nodiscard]] const TEventSubtype* getIf() const;
|
[[nodiscard]] const TEventSubtype* getIf() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Apply a visitor to the event
|
/// \brief Apply handlers to the event
|
||||||
///
|
///
|
||||||
/// \param visitor The visitor to apply
|
/// \param handlers Handlers to apply
|
||||||
///
|
///
|
||||||
/// \return The result of applying the visitor to the event
|
/// \return The result of applying the handlers to the event
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename... Handlers>
|
||||||
decltype(auto) visit(T&& visitor);
|
decltype(auto) visit(Handlers&&... handlers);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Apply a visitor to the event
|
/// \brief Apply handlers to the event
|
||||||
///
|
///
|
||||||
/// \param visitor The visitor to apply
|
/// \param handlers Handlers to apply
|
||||||
///
|
///
|
||||||
/// \return The result of applying the visitor to the event
|
/// \return The result of applying the handlers to the event
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename... Handlers>
|
||||||
decltype(auto) visit(T&& visitor) const;
|
decltype(auto) visit(Handlers&&... handlers) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@ -395,11 +396,20 @@ private:
|
|||||||
template <typename T, typename... Ts>
|
template <typename T, typename... Ts>
|
||||||
[[nodiscard]] static constexpr bool isInParameterPack(const std::variant<Ts...>*)
|
[[nodiscard]] static constexpr bool isInParameterPack(const std::variant<Ts...>*)
|
||||||
{
|
{
|
||||||
return (std::is_same_v<T, Ts> || ...);
|
return std::disjunction_v<std::is_same<T, Ts>...>;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static constexpr bool isEventSubtype = isInParameterPack<T>(decltype (&m_data)(nullptr));
|
static constexpr bool isEventSubtype = isInParameterPack<T>(static_cast<decltype(&m_data)>(nullptr));
|
||||||
|
|
||||||
|
template <typename Handler, typename... Ts>
|
||||||
|
static constexpr bool isInvokableWithAnyOf(std::variant<Ts...>*)
|
||||||
|
{
|
||||||
|
return std::disjunction_v<std::is_invocable<Handler, Ts&>...>;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
static constexpr bool isValidHandler = isInvokableWithAnyOf<Handler>(static_cast<decltype(&m_data)>(nullptr));
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -38,6 +38,20 @@
|
|||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
|
namespace priv
|
||||||
|
{
|
||||||
|
template <typename... Ts>
|
||||||
|
struct OverloadSet : Ts...
|
||||||
|
{
|
||||||
|
using Ts::operator()...;
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
unsigned char dummy; // Dummy variable to ensure that this struct is not empty thus avoiding a crash due to an MSVC bug
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
template <typename... Ts>
|
||||||
|
OverloadSet(Ts...) -> OverloadSet<Ts...>;
|
||||||
|
} // namespace priv
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
template <typename TEventSubtype>
|
template <typename TEventSubtype>
|
||||||
Event::Event(const TEventSubtype& eventSubtype)
|
Event::Event(const TEventSubtype& eventSubtype)
|
||||||
@ -79,18 +93,20 @@ const TEventSubtype* Event::getIf() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename... Handlers>
|
||||||
decltype(auto) Event::visit(T&& visitor)
|
decltype(auto) Event::visit(Handlers&&... handlers)
|
||||||
{
|
{
|
||||||
return std::visit(std::forward<T>(visitor), m_data);
|
static_assert((isValidHandler<Handlers> && ...), "All handlers must accept a single event subtype parameter");
|
||||||
|
return std::visit(priv::OverloadSet{std::forward<Handlers>(handlers)...}, m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename... Handlers>
|
||||||
decltype(auto) Event::visit(T&& visitor) const
|
decltype(auto) Event::visit(Handlers&&... handlers) const
|
||||||
{
|
{
|
||||||
return std::visit(std::forward<T>(visitor), m_data);
|
static_assert((isValidHandler<Handlers> && ...), "All handlers must accept a single event subtype parameter");
|
||||||
|
return std::visit(priv::OverloadSet{std::forward<Handlers>(handlers)...}, m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
@ -35,17 +35,6 @@ namespace sf
|
|||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
{
|
{
|
||||||
template <typename... Ts>
|
|
||||||
struct OverloadSet : Ts...
|
|
||||||
{
|
|
||||||
using Ts::operator()...;
|
|
||||||
#if defined(_MSC_VER) && !defined(__clang__)
|
|
||||||
unsigned char dummy; // Dummy variable to ensure that this struct is not empty thus avoiding a crash due to an MSVC bug
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
template <typename... Ts>
|
|
||||||
OverloadSet(Ts...) -> OverloadSet<Ts...>;
|
|
||||||
|
|
||||||
struct DelayOverloadResolution
|
struct DelayOverloadResolution
|
||||||
{
|
{
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -55,21 +44,14 @@ struct DelayOverloadResolution
|
|||||||
};
|
};
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
template <typename... Ts>
|
template <typename... Handlers>
|
||||||
void WindowBase::handleEvents(Ts&&... handlers) // NOLINT(cppcoreguidelines-missing-std-forward)
|
void WindowBase::handleEvents(Handlers&&... handlers)
|
||||||
{
|
{
|
||||||
static_assert(sizeof...(Ts) > 0, "Must provide at least one handler");
|
static_assert(sizeof...(Handlers) > 0, "Must provide at least one handler");
|
||||||
|
|
||||||
// Disable misc-const-correctness for this line since clang-tidy
|
|
||||||
// complains about it even though the code would become uncompilable
|
|
||||||
|
|
||||||
// NOLINTNEXTLINE(misc-const-correctness)
|
|
||||||
priv::OverloadSet overloadSet{std::forward<Ts>(handlers)..., [](const priv::DelayOverloadResolution&) { /* ignore */ }};
|
|
||||||
|
|
||||||
while (std::optional event = pollEvent())
|
while (std::optional event = pollEvent())
|
||||||
event->visit(overloadSet);
|
event->visit(std::forward<Handlers>(handlers)..., [](priv::DelayOverloadResolution) { /* ignore */ });
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sf
|
} // namespace sf
|
||||||
|
Loading…
Reference in New Issue
Block a user