44#include <initializer_list>
62#if !defined(COMMONS_PRIORITIZED_HIGHEST_PRECEDENCE)
63#define COMMONS_PRIORITIZED_HIGHEST_PRECEDENCE (std::numeric_limits<int>::min())
65#if !defined(COMMONS_PRIORITIZED_LOWEST_PRECEDENCE)
66#define COMMONS_PRIORITIZED_LOWEST_PRECEDENCE (std::numeric_limits<int>::max())
68#if !defined(COMMONS_PRIORITIZED_DEFAULT_PRIORITY)
69#define COMMONS_PRIORITIZED_DEFAULT_PRIORITY 0
102 [[nodiscard]]
virtual int priority() const noexcept {
118 { t.priority() } -> std::convertible_to<int>;
130 { t.get() } -> std::convertible_to<const volatile void*>;
139 if (ptr ==
nullptr) {
143 return ptr->priority();
144 }
else if constexpr (std::is_polymorphic_v<T>) {
145 if (
const auto* p =
dynamic_cast<const Prioritized*
>(ptr)) {
146 return p->priority();
163 requires(!std::is_pointer_v<T>)
166 return value.priority();
168 return detail::get_priority_ptr(value.get());
178 return detail::get_priority_ptr(ptr);
189 [[nodiscard]]
bool operator()(
const std::shared_ptr<Prioritized>& a,
190 const std::shared_ptr<Prioritized>& b)
const noexcept {
195 return std::less<const Prioritized*>{}(a.get(), b.get());
206 [[nodiscard]]
bool operator()(
const std::shared_ptr<T>& a,
207 const std::shared_ptr<T>& b)
const noexcept {
212 return std::less<const T*>{}(a.get(), b.get());
242 static_assert(std::equality_comparable<T>,
243 "PrioritizedSet<T> requires T to be equality-comparable");
255 [[nodiscard]]
bool operator()(
const Item& a,
const Item& b)
const noexcept {
256 if (a.priority != b.priority) {
257 return a.priority < b.priority;
259 return a.order < b.order;
263 using set_type = std::set<Item, ItemCompare>;
267 using value_type = T;
268 using size_type = std::size_t;
269 using difference_type = std::ptrdiff_t;
270 using reference =
const T&;
271 using const_reference =
const T&;
281 using iterator_category = std::bidirectional_iterator_tag;
282 using value_type = T;
283 using difference_type = std::ptrdiff_t;
284 using pointer =
const T*;
285 using reference =
const T&;
289 [[nodiscard]] reference operator*()
const noexcept {
292 [[nodiscard]] pointer operator->()
const noexcept {
319 explicit const_iterator(
typename set_type::const_iterator it) noexcept : it_(it) {}
320 typename set_type::const_iterator it_{};
324 using reverse_iterator = std::reverse_iterator<iterator>;
325 using const_reverse_iterator = reverse_iterator;
330 for (
const auto& v : init) {
335 template <
typename It>
336 PrioritizedSet(It first, It last) {
337 for (; first != last; ++first) {
346 std::pair<iterator, bool>
insert(
const T& v) {
350 std::pair<iterator, bool>
insert(T&& v) {
352 return insert(p, std::move(v));
358 std::pair<iterator, bool>
insert(
int priority, T v) {
359 if (
const auto found = find_item(v); found != items_.end()) {
362 const auto [it, ok] = items_.insert(
363 Item{.value = std::move(v), .priority = priority, .order = next_order_++});
368 template <
typename... Args>
369 std::pair<iterator, bool>
emplace(Args&&... args) {
370 return insert(T(std::forward<Args>(args)...));
373 void insert(std::initializer_list<T> init) {
374 for (
const auto& v : init) {
379 template <
typename It>
380 void insert(It first, It last) {
381 for (; first != last; ++first) {
386 iterator erase(const_iterator pos) {
387 return const_iterator{items_.erase(pos.it_)};
390 iterator erase(const_iterator first, const_iterator last) {
391 return const_iterator{items_.erase(first.it_, last.it_)};
396 const auto it = find_item(v);
397 if (it == items_.end()) {
410 [[nodiscard]] size_type
count(
const T& v)
const {
411 return contains(v) ? 1U : 0U;
414 [[nodiscard]]
bool contains(
const T& v)
const {
415 return find_item(v) != items_.end();
422 const auto it = find_item(v);
429 const auto it = find_item(v);
430 if (it == items_.end()) {
433 if (it->priority == priority) {
437 updated.priority = priority;
439 items_.insert(std::move(updated));
443 [[nodiscard]] size_type size() const noexcept {
444 return items_.size();
446 [[nodiscard]]
bool empty() const noexcept {
447 return items_.empty();
457 items_.swap(other.items_);
458 std::swap(next_order_, other.next_order_);
461 [[nodiscard]] iterator begin() const noexcept {
462 return const_iterator{items_.begin()};
464 [[nodiscard]] iterator end() const noexcept {
465 return const_iterator{items_.end()};
467 [[nodiscard]] iterator cbegin() const noexcept {
470 [[nodiscard]] iterator cend() const noexcept {
473 [[nodiscard]] reverse_iterator rbegin() const noexcept {
474 return reverse_iterator{end()};
476 [[nodiscard]] reverse_iterator rend() const noexcept {
477 return reverse_iterator{begin()};
479 [[nodiscard]] const_reverse_iterator crbegin() const noexcept {
482 [[nodiscard]] const_reverse_iterator crend() const noexcept {
488 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
492 [[nodiscard]]
typename set_type::const_iterator find_item(
const T& v)
const {
493 for (
auto it = items_.begin(); it != items_.end(); ++it) {
494 if (it->value == v) {
506void swap(PrioritizedSet<T>& a, PrioritizedSet<T>& b)
noexcept {
521template <
typename Derived>
524 [[nodiscard]]
int priority() const noexcept
override {
534 Derived& highest_priority() noexcept {
539 Derived& lowest_priority() noexcept {
548 Derived& self() noexcept {
549 return static_cast<Derived&
>(*this);
568class WithPriorityInherit :
public T,
public Prioritized {
570 using value_type = T;
572 template <
typename... Args>
573 explicit WithPriorityInherit(
const int p, Args&&... args)
574 : T(std::forward<Args>(args)...), priority_(p) {}
576 [[nodiscard]]
int priority()
const noexcept override {
579 void set_priority(
const int p)
noexcept {
583 [[nodiscard]] T& value()
noexcept {
584 return static_cast<T&
>(*this);
586 [[nodiscard]]
const T& value()
const noexcept {
587 return static_cast<const T&
>(*this);
599 using value_type = T;
601 template <
typename... Args>
602 explicit WithPriorityCompose(
const int p, Args&&... args)
603 : value_(std::forward<Args>(args)...), priority_(p) {}
605 [[nodiscard]]
int priority()
const noexcept override {
608 void set_priority(
const int p)
noexcept {
612 [[nodiscard]] T& value()
noexcept {
615 [[nodiscard]]
const T& value()
const noexcept {
619 [[nodiscard]] T& operator*()
noexcept {
622 [[nodiscard]]
const T& operator*()
const noexcept {
625 [[nodiscard]] T* operator->()
noexcept {
628 [[nodiscard]]
const T* operator->()
const noexcept {
638using WithPriorityBase =
639 std::conditional_t<with_priority_inherits<T>, WithPriorityInherit<T>, WithPriorityCompose<T>>;
651 using base = detail::WithPriorityBase<T>;
654 using value_type = T;
660 requires std::default_initializable<T>
674template <
typename T,
typename... Args>
676 return std::make_shared<WithPriority<T>>(p, std::forward<Args>(args)...);
CRTP mixin that makes Derived a Prioritized carrying a mutable priority, with fluent setters returnin...
Definition prioritized.hpp:522
int priority() const noexcept override
This object's priority; lower sorts first. Defaults to DEFAULT_PRIORITY.
Definition prioritized.hpp:524
Derived & priority(const int p) noexcept
Set the priority. Same-scope overload of the priority() getter above.
Definition prioritized.hpp:529
A thin bidirectional adapter over std::set<Item>::const_iterator that projects each Item to its const...
Definition prioritized.hpp:279
A set that behaves like std::set<T> from the outside — unique by T value, iterators yield const T&,...
Definition prioritized.hpp:241
bool set_priority(const T &v, int priority)
Re-snapshot v's priority and reorder it, keeping its insertion-order tie-break.
Definition prioritized.hpp:428
std::pair< iterator, bool > emplace(Args &&... args)
Construct a T from args and insert it at its discovered priority.
Definition prioritized.hpp:369
iterator find(const T &v) const
Linear lookup by value; end() when absent.
Definition prioritized.hpp:405
size_type count(const T &v) const
0 or 1 — elements are unique by value.
Definition prioritized.hpp:410
friend bool operator==(const PrioritizedSet &a, const PrioritizedSet &b)
Element-wise comparison over the ordered T sequence.
Definition prioritized.hpp:487
std::pair< iterator, bool > insert(const T &v)
Insert v at its discovered priority (get_priority(v), i.e.
Definition prioritized.hpp:346
size_type erase(const T &v)
Erase the element equal to v. Returns 0 or 1.
Definition prioritized.hpp:395
std::pair< iterator, bool > insert(int priority, T v)
Priority-aware addition.
Definition prioritized.hpp:358
void clear() noexcept
Remove all elements.
Definition prioritized.hpp:452
int priority_of(const T &v) const
The snapshotted priority of v, or DEFAULT_PRIORITY if absent.
Definition prioritized.hpp:421
A value of T carrying a priority.
Definition prioritized.hpp:650
WithPriority()
Default-constructs a T at DEFAULT_PRIORITY — available only when T is default-constructible (needed f...
Definition prioritized.hpp:659
Any type exposing a priority() convertible to int — satisfied by types deriving from Prioritized and ...
Definition prioritized.hpp:117
A type whose .get() yields something pointer-like (a smart pointer).
Definition prioritized.hpp:129
constexpr bool with_priority_inherits
Whether WithPriority<T> attaches its priority by inheritance (a true is-a T): only for non-final clas...
Definition prioritized.hpp:561
std::shared_ptr< WithPriority< T > > make_prioritized(int p, Args &&... args)
Make a shared_ptr<WithPriority<T>> (for use with the comparators / a std::set).
Definition prioritized.hpp:675
int get_priority_ptr(const T *ptr) noexcept
Priority of a pointee.
Definition prioritized.hpp:138
#define COMMONS_PRIORITIZED_HIGHEST_PRECEDENCE
Override for comms::Prioritized::HIGHEST_PRECEDENCE (default INT_MIN).
Definition prioritized.hpp:63
#define COMMONS_PRIORITIZED_LOWEST_PRECEDENCE
Override for comms::Prioritized::LOWEST_PRECEDENCE (default INT_MAX).
Definition prioritized.hpp:66
int get_priority(const T &value) noexcept
Priority of a value or reference.
Definition prioritized.hpp:164
#define COMMONS_PRIORITIZED_DEFAULT_PRIORITY
Override for comms::Prioritized::DEFAULT_PRIORITY (default 0).
Definition prioritized.hpp:69
WithPriority< std::remove_cvref_t< T > > with_priority(int p, T &&item)
Wrap item with priority p.
Definition prioritized.hpp:668
Like PrioritizedCompare, but over std::shared_ptr<T> for an arbitrary T that need not derive from Pri...
Definition prioritized.hpp:205
Orders std::shared_ptr<Prioritized> by ascending priority.
Definition prioritized.hpp:188
The orderable interface.
Definition prioritized.hpp:86
static constexpr int HIGHEST_PRECEDENCE
Most-preferred priority (INT_MIN): sorts before everything else.
Definition prioritized.hpp:92
static constexpr int DEFAULT_PRIORITY
The neutral priority (0) reported when none is set.
Definition prioritized.hpp:96
static constexpr int LOWEST_PRECEDENCE
Least-preferred priority (INT_MAX): sorts after everything else.
Definition prioritized.hpp:94
virtual int priority() const noexcept
This object's priority; lower sorts first. Defaults to DEFAULT_PRIORITY.
Definition prioritized.hpp:102
Fixed-width numeric aliases shared across the C++ libraries.
std::uint64_t u64
Unsigned 64-bit integer.
Definition types.hpp:25