From 17d387cd1a74f527bc43dd06305480b088e42bae Mon Sep 17 00:00:00 2001 From: Pixel-Tony Date: Sat, 4 Jan 2025 00:41:13 +0100 Subject: [PATCH] Provide additional checks for event handlers --- include/SFML/Window/Event.hpp | 13 +++++++++++++ include/SFML/Window/WindowBase.inl | 2 ++ test/Window/WindowBase.test.cpp | 1 + 3 files changed, 16 insertions(+) diff --git a/include/SFML/Window/Event.hpp b/include/SFML/Window/Event.hpp index f68a29b47..8ef7d2cce 100644 --- a/include/SFML/Window/Event.hpp +++ b/include/SFML/Window/Event.hpp @@ -389,6 +389,19 @@ private: template static constexpr bool isEventSubtype = isInParameterPack(decltype (&m_data)(nullptr)); + + template + static constexpr bool isInvokableWithAnyOf(std::variant*) + { + return (std::is_invocable_v || ...); + } + +public: + template + static constexpr bool isValidHandler() + { + return isInvokableWithAnyOf(static_cast(nullptr)); + } }; } // namespace sf diff --git a/include/SFML/Window/WindowBase.inl b/include/SFML/Window/WindowBase.inl index e1af3c79e..772b487c4 100644 --- a/include/SFML/Window/WindowBase.inl +++ b/include/SFML/Window/WindowBase.inl @@ -61,6 +61,8 @@ template void WindowBase::handleEvents(Ts&&... handlers) // NOLINT(cppcoreguidelines-missing-std-forward) { static_assert(sizeof...(Ts) > 0, "Must provide at least one handler"); + static_assert((Event::isValidHandler() && ...), + "All event handlers must accept a single parameter, either a const reference or a value"); // Disable misc-const-correctness for this line since clang-tidy // complains about it even though the code would become uncompilable diff --git a/test/Window/WindowBase.test.cpp b/test/Window/WindowBase.test.cpp index 66b01befc..470e0d2ba 100644 --- a/test/Window/WindowBase.test.cpp +++ b/test/Window/WindowBase.test.cpp @@ -213,6 +213,7 @@ TEST_CASE("[Window] sf::WindowBase", runDisplayTests()) // Should compile if user provides only a specific handler windowBase.handleEvents([](const sf::Event::Closed&) {}); + windowBase.handleEvents([](sf::Event::Closed) {}); // Should compile if user provides only a catch-all windowBase.handleEvents([](const auto&) {});