From c7a0597fe7e1a103b9a143a093a0beab2d20a076 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 1 Dec 2022 15:02:39 +0100 Subject: [PATCH] util/Intrusive*: add C++20 concept checks --- src/util/Concepts.hxx | 17 +++++++++++++++++ src/util/IntrusiveForwardList.hxx | 4 ++-- src/util/IntrusiveHashSet.hxx | 11 ++++++----- src/util/IntrusiveList.hxx | 15 +++++++-------- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/util/Concepts.hxx b/src/util/Concepts.hxx index d24ddc5a8..ecc7bf40b 100644 --- a/src/util/Concepts.hxx +++ b/src/util/Concepts.hxx @@ -31,6 +31,20 @@ #include +/** + * Compatibility wrapper for std::invocable which is unavailable in + * the Android NDK r25b and Apple Xcode. + */ +#if !defined(ANDROID) && !defined(__APPLE__) +template +concept Invocable = std::invocable; +#else +template +concept Invocable = requires(F f, Args... args) { + { f(args...) }; +}; +#endif + /** * Compatibility wrapper for std::predicate which is unavailable in * the Android NDK r25b and Apple Xcode. @@ -44,3 +58,6 @@ concept Predicate = requires(F f, Args... args) { { f(args...) } -> std::same_as; }; #endif + +template +concept Disposer = Invocable; diff --git a/src/util/IntrusiveForwardList.hxx b/src/util/IntrusiveForwardList.hxx index f496ea9d6..61d7f973f 100644 --- a/src/util/IntrusiveForwardList.hxx +++ b/src/util/IntrusiveForwardList.hxx @@ -33,6 +33,7 @@ #pragma once #include "Cast.hxx" +#include "Concepts.hxx" #include "MemberPointer.hxx" #include "OptionalCounter.hxx" #include "ShallowCopy.hxx" @@ -198,8 +199,7 @@ public: counter.reset(); } - template - void clear_and_dispose(D &&disposer) noexcept { + void clear_and_dispose(Disposer auto disposer) noexcept { while (!empty()) { auto *item = &front(); pop_front(); diff --git a/src/util/IntrusiveHashSet.hxx b/src/util/IntrusiveHashSet.hxx index d747979d8..f2b686681 100644 --- a/src/util/IntrusiveHashSet.hxx +++ b/src/util/IntrusiveHashSet.hxx @@ -29,6 +29,7 @@ #pragma once +#include "Concepts.hxx" #include "IntrusiveList.hxx" #include // for std::all_of() @@ -192,15 +193,15 @@ public: counter.reset(); } - template - constexpr void clear_and_dispose(D &&disposer) noexcept { + constexpr void clear_and_dispose(Disposer auto disposer) noexcept { for (auto &i : table) i.clear_and_dispose(disposer); counter.reset(); } - void remove_and_dispose_if(auto &&pred, auto &&disposer) noexcept { + void remove_and_dispose_if(Predicate auto pred, + Disposer auto disposer) noexcept { static_assert(!constant_time_size, "Not yet implemented"); for (auto &bucket : table) @@ -238,7 +239,7 @@ public: } constexpr bucket_iterator erase_and_dispose(bucket_iterator i, - auto &&disposer) noexcept { + Disposer auto disposer) noexcept { auto result = erase(i); disposer(&*i); return result; @@ -272,7 +273,7 @@ public: */ [[nodiscard]] [[gnu::pure]] constexpr bucket_iterator find_if(const auto &key, - auto &&pred) noexcept { + Disposer auto pred) noexcept { auto &bucket = GetBucket(key); for (auto &i : bucket) if (equal(key, i) && pred(i)) diff --git a/src/util/IntrusiveList.hxx b/src/util/IntrusiveList.hxx index 5abd7bce5..0006d190a 100644 --- a/src/util/IntrusiveList.hxx +++ b/src/util/IntrusiveList.hxx @@ -30,6 +30,7 @@ #pragma once #include "Cast.hxx" +#include "Concepts.hxx" #include "IntrusiveHookMode.hxx" #include "MemberPointer.hxx" #include "OptionalCounter.hxx" @@ -287,8 +288,7 @@ public: } } - template - void clear_and_dispose(D &&disposer) noexcept { + void clear_and_dispose(Disposer auto disposer) noexcept { while (!empty()) { auto *item = &front(); pop_front(); @@ -296,8 +296,8 @@ public: } } - template - void remove_and_dispose_if(P &&pred, D &&dispose) noexcept { + void remove_and_dispose_if(Predicate auto pred, + Disposer auto dispose) noexcept { auto *n = head.next; while (n != &head) { @@ -325,8 +325,7 @@ public: --counter; } - template - void pop_front_and_dispose(D &&disposer) noexcept { + void pop_front_and_dispose(Disposer auto disposer) noexcept { auto &i = front(); ToHook(i).unlink(); --counter; @@ -479,8 +478,8 @@ public: return result; } - template - iterator erase_and_dispose(iterator i, D &&disposer) noexcept { + iterator erase_and_dispose(iterator i, + Disposer auto disposer) noexcept { auto result = erase(i); disposer(&*i); return result;