util/Intrusive*: add C++20 concept checks

This commit is contained in:
Max Kellermann 2022-12-01 15:02:39 +01:00
parent 253d551684
commit c7a0597fe7
4 changed files with 32 additions and 15 deletions

View File

@ -31,6 +31,20 @@
#include <concepts> #include <concepts>
/**
* Compatibility wrapper for std::invocable which is unavailable in
* the Android NDK r25b and Apple Xcode.
*/
#if !defined(ANDROID) && !defined(__APPLE__)
template<typename F, typename... Args>
concept Invocable = std::invocable<F, Args...>;
#else
template<typename F, typename... Args>
concept Invocable = requires(F f, Args... args) {
{ f(args...) };
};
#endif
/** /**
* Compatibility wrapper for std::predicate which is unavailable in * Compatibility wrapper for std::predicate which is unavailable in
* the Android NDK r25b and Apple Xcode. * the Android NDK r25b and Apple Xcode.
@ -44,3 +58,6 @@ concept Predicate = requires(F f, Args... args) {
{ f(args...) } -> std::same_as<bool>; { f(args...) } -> std::same_as<bool>;
}; };
#endif #endif
template<typename F, typename T>
concept Disposer = Invocable<F, T *>;

View File

@ -33,6 +33,7 @@
#pragma once #pragma once
#include "Cast.hxx" #include "Cast.hxx"
#include "Concepts.hxx"
#include "MemberPointer.hxx" #include "MemberPointer.hxx"
#include "OptionalCounter.hxx" #include "OptionalCounter.hxx"
#include "ShallowCopy.hxx" #include "ShallowCopy.hxx"
@ -198,8 +199,7 @@ public:
counter.reset(); counter.reset();
} }
template<typename D> void clear_and_dispose(Disposer<value_type> auto disposer) noexcept {
void clear_and_dispose(D &&disposer) noexcept {
while (!empty()) { while (!empty()) {
auto *item = &front(); auto *item = &front();
pop_front(); pop_front();

View File

@ -29,6 +29,7 @@
#pragma once #pragma once
#include "Concepts.hxx"
#include "IntrusiveList.hxx" #include "IntrusiveList.hxx"
#include <algorithm> // for std::all_of() #include <algorithm> // for std::all_of()
@ -192,15 +193,15 @@ public:
counter.reset(); counter.reset();
} }
template<typename D> constexpr void clear_and_dispose(Disposer<value_type> auto disposer) noexcept {
constexpr void clear_and_dispose(D &&disposer) noexcept {
for (auto &i : table) for (auto &i : table)
i.clear_and_dispose(disposer); i.clear_and_dispose(disposer);
counter.reset(); counter.reset();
} }
void remove_and_dispose_if(auto &&pred, auto &&disposer) noexcept { void remove_and_dispose_if(Predicate<const_reference> auto pred,
Disposer<value_type> auto disposer) noexcept {
static_assert(!constant_time_size, "Not yet implemented"); static_assert(!constant_time_size, "Not yet implemented");
for (auto &bucket : table) for (auto &bucket : table)
@ -238,7 +239,7 @@ public:
} }
constexpr bucket_iterator erase_and_dispose(bucket_iterator i, constexpr bucket_iterator erase_and_dispose(bucket_iterator i,
auto &&disposer) noexcept { Disposer<value_type> auto disposer) noexcept {
auto result = erase(i); auto result = erase(i);
disposer(&*i); disposer(&*i);
return result; return result;
@ -272,7 +273,7 @@ public:
*/ */
[[nodiscard]] [[gnu::pure]] [[nodiscard]] [[gnu::pure]]
constexpr bucket_iterator find_if(const auto &key, constexpr bucket_iterator find_if(const auto &key,
auto &&pred) noexcept { Disposer<value_type> auto pred) noexcept {
auto &bucket = GetBucket(key); auto &bucket = GetBucket(key);
for (auto &i : bucket) for (auto &i : bucket)
if (equal(key, i) && pred(i)) if (equal(key, i) && pred(i))

View File

@ -30,6 +30,7 @@
#pragma once #pragma once
#include "Cast.hxx" #include "Cast.hxx"
#include "Concepts.hxx"
#include "IntrusiveHookMode.hxx" #include "IntrusiveHookMode.hxx"
#include "MemberPointer.hxx" #include "MemberPointer.hxx"
#include "OptionalCounter.hxx" #include "OptionalCounter.hxx"
@ -287,8 +288,7 @@ public:
} }
} }
template<typename D> void clear_and_dispose(Disposer<value_type> auto disposer) noexcept {
void clear_and_dispose(D &&disposer) noexcept {
while (!empty()) { while (!empty()) {
auto *item = &front(); auto *item = &front();
pop_front(); pop_front();
@ -296,8 +296,8 @@ public:
} }
} }
template<typename P, typename D> void remove_and_dispose_if(Predicate<const_reference> auto pred,
void remove_and_dispose_if(P &&pred, D &&dispose) noexcept { Disposer<value_type> auto dispose) noexcept {
auto *n = head.next; auto *n = head.next;
while (n != &head) { while (n != &head) {
@ -325,8 +325,7 @@ public:
--counter; --counter;
} }
template<typename D> void pop_front_and_dispose(Disposer<value_type> auto disposer) noexcept {
void pop_front_and_dispose(D &&disposer) noexcept {
auto &i = front(); auto &i = front();
ToHook(i).unlink(); ToHook(i).unlink();
--counter; --counter;
@ -479,8 +478,8 @@ public:
return result; return result;
} }
template<typename D> iterator erase_and_dispose(iterator i,
iterator erase_and_dispose(iterator i, D &&disposer) noexcept { Disposer<value_type> auto disposer) noexcept {
auto result = erase(i); auto result = erase(i);
disposer(&*i); disposer(&*i);
return result; return result;