Simplify sf::WindowBase::handleEvents and add basic tests

This commit is contained in:
vittorioromeo 2024-07-09 16:34:55 +02:00 committed by Vittorio Romeo
parent 2a6e15f9cc
commit 7ba672139c
2 changed files with 23 additions and 13 deletions

View File

@ -28,7 +28,7 @@
#include <SFML/Window/Event.hpp> #include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowBase.hpp> // NOLINT(misc-header-include-cycle) #include <SFML/Window/WindowBase.hpp> // NOLINT(misc-header-include-cycle)
#include <type_traits> #include <utility>
namespace sf namespace sf
@ -43,22 +43,13 @@ struct OverloadSet : Ts...
template <typename... Ts> template <typename... Ts>
OverloadSet(Ts...) -> OverloadSet<Ts...>; OverloadSet(Ts...) -> OverloadSet<Ts...>;
template <typename... Ts> struct DelayOverloadResolution
struct OverloadSetWithDefault : OverloadSet<Ts...>
{ {
// By providing our own operator() and forwarding based
// on invocability of OverloadSet<Ts...> on the concrete type
// of the value, we save the user from having to provide
// their own catch-all overload if they don't want to
template <typename T> template <typename T>
void operator()([[maybe_unused]] T&& value) // NOLINT(cppcoreguidelines-missing-std-forward) DelayOverloadResolution(const T&)
{ {
if constexpr (std::is_invocable_v<OverloadSet<Ts...>, T>)
OverloadSet<Ts...>::operator()(std::forward<T>(value));
} }
}; };
template <typename... Ts>
OverloadSetWithDefault(Ts...) -> OverloadSetWithDefault<Ts...>;
} // namespace priv } // namespace priv
@ -68,7 +59,9 @@ void WindowBase::handleEvents(Ts&&... handlers) // NOLINT(cppcoreguidelines-miss
{ {
// 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 uncompilable // complains about it even though the code would become uncompilable
priv::OverloadSetWithDefault overloadSet{std::forward<Ts>(handlers)...}; // NOLINT(misc-const-correctness)
// NOLINTNEXTLINE(misc-const-correctness)
priv::OverloadSet overloadSet{std::forward<Ts>(handlers)..., [](const priv::DelayOverloadResolution&) { /* ignore */ }};
while (const std::optional event = pollEvent()) while (const std::optional event = pollEvent())
event->visit(overloadSet); event->visit(overloadSet);

View File

@ -195,4 +195,21 @@ TEST_CASE("[Window] sf::WindowBase", runDisplayTests())
CHECK(windowBase.getSize() == sf::Vector2u(200, 300)); CHECK(windowBase.getSize() == sf::Vector2u(200, 300));
windowBase.setMinimumSize(sf::Vector2u(200, 300)); windowBase.setMinimumSize(sf::Vector2u(200, 300));
} }
SECTION("handleEvents()")
{
sf::WindowBase windowBase(sf::VideoMode({360, 240}), "WindowBase Tests");
// Should compile if user provides nothing
windowBase.handleEvents();
// Should compile if user provides only a specific handler
windowBase.handleEvents([](const sf::Event::Closed&) {});
// Should compile if user provides only a catch-all
windowBase.handleEvents([](const auto&) {});
// Should compile if user provides both a specific handler and a catch-all
windowBase.handleEvents([](const sf::Event::Closed&) {}, [](const auto&) {});
}
} }