mirror of
https://github.com/SFML/SFML.git
synced 2025-01-31 13:45:13 +08:00
Check that all WindowBase::handleEvents arguments handle some events
This commit is contained in:
parent
23afdc2f9e
commit
efb207c849
@ -34,6 +34,7 @@
|
||||
|
||||
#include <SFML/System/Vector2.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
|
||||
@ -395,11 +396,22 @@ private:
|
||||
template <typename T, typename... 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>
|
||||
static constexpr bool isEventSubtype = isInParameterPack<T>(decltype (&m_data)(nullptr));
|
||||
|
||||
friend class WindowBase;
|
||||
|
||||
template <typename Handler, typename... Ts>
|
||||
[[nodiscard]] static constexpr bool isInvocableWithEventSubtype(const std::variant<Ts...>*)
|
||||
{
|
||||
return std::disjunction_v<std::is_invocable<Handler&, Ts&>...>;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
static constexpr bool isEventHandler = isInvocableWithEventSubtype<Handler>(decltype (&m_data)(nullptr));
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
@ -61,6 +61,7 @@ template <typename... Handlers>
|
||||
void WindowBase::handleEvents(Handlers&&... handlers)
|
||||
{
|
||||
static_assert(sizeof...(Handlers) > 0, "Must provide at least one handler");
|
||||
static_assert((Event::isEventHandler<Handlers> && ...), "Handlers must accept at least one subtype of sf::Event");
|
||||
|
||||
// Disable misc-const-correctness for this line since clang-tidy
|
||||
// complains about it even though the code would become incorrect
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include <WindowUtil.hpp>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
TEST_CASE("[Window] sf::WindowBase", runDisplayTests())
|
||||
@ -219,5 +220,25 @@ TEST_CASE("[Window] sf::WindowBase", runDisplayTests())
|
||||
|
||||
// Should compile if user provides both a specific handler and a catch-all
|
||||
windowBase.handleEvents([](const sf::Event::Closed&) {}, [](const auto&) {});
|
||||
|
||||
// Should compile if user provides a handler taking an event subtype by value or reference,
|
||||
// but not rvalue reference because it would never be called.
|
||||
windowBase.handleEvents([](sf::Event::Closed) {});
|
||||
windowBase.handleEvents([](const sf::Event::Closed) {});
|
||||
windowBase.handleEvents([](sf::Event::Closed&) {});
|
||||
windowBase.handleEvents([](const sf::Event::Closed&) {});
|
||||
|
||||
// Should compile if user provides a move-only handler
|
||||
windowBase.handleEvents([p = std::make_unique<int>()](const sf::Event::Closed&) {});
|
||||
|
||||
// Should compile if user provides a handler with deleted rvalue ref-qualified call operator
|
||||
struct LvalueOnlyHandler
|
||||
{
|
||||
void operator()(const sf::Event::Closed&) &
|
||||
{
|
||||
}
|
||||
void operator()(const sf::Event::Closed&) && = delete;
|
||||
};
|
||||
windowBase.handleEvents(LvalueOnlyHandler{});
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user