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 <SFML/System/Vector2.hpp>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
|
||||||
@ -395,11 +396,22 @@ 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>(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
|
} // namespace sf
|
||||||
|
@ -61,6 +61,7 @@ template <typename... Handlers>
|
|||||||
void WindowBase::handleEvents(Handlers&&... handlers)
|
void WindowBase::handleEvents(Handlers&&... handlers)
|
||||||
{
|
{
|
||||||
static_assert(sizeof...(Handlers) > 0, "Must provide at least one handler");
|
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
|
// Disable misc-const-correctness for this line since clang-tidy
|
||||||
// complains about it even though the code would become incorrect
|
// complains about it even though the code would become incorrect
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <WindowUtil.hpp>
|
#include <WindowUtil.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
TEST_CASE("[Window] sf::WindowBase", runDisplayTests())
|
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
|
// Should compile if user provides both a specific handler and a catch-all
|
||||||
windowBase.handleEvents([](const sf::Event::Closed&) {}, [](const auto&) {});
|
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