mirror of
https://github.com/Neargye/magic_enum.git
synced 2026-01-09 23:34:23 +00:00
fix clang-format
This commit is contained in:
parent
dd2fb1b9a3
commit
50adc0691e
6 changed files with 133 additions and 142 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
||||||
|
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
||||||
|
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
||||||
|
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
||||||
// Copyright (c) 2020 - 2023 Bela Schaum <schaumb@gmail.com>.
|
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
||||||
// Copyright (c) 2023 - 2023 Bela Schaum <schaumb@gmail.com>.
|
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -33,10 +33,10 @@
|
||||||
#ifndef NEARGYE_MAGIC_ENUM_CONTAINERS_HPP
|
#ifndef NEARGYE_MAGIC_ENUM_CONTAINERS_HPP
|
||||||
#define NEARGYE_MAGIC_ENUM_CONTAINERS_HPP
|
#define NEARGYE_MAGIC_ENUM_CONTAINERS_HPP
|
||||||
|
|
||||||
#include "magic_enum.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "magic_enum.hpp"
|
||||||
|
|
||||||
namespace magic_enum::containers {
|
namespace magic_enum::containers {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
@ -48,7 +48,7 @@ template <typename T>
|
||||||
constexpr static bool is_transparent_v<T, std::void_t<typename T::is_transparent>>{true};
|
constexpr static bool is_transparent_v<T, std::void_t<typename T::is_transparent>>{true};
|
||||||
|
|
||||||
template <typename Eq = std::equal_to<>, typename T1, typename T2>
|
template <typename Eq = std::equal_to<>, typename T1, typename T2>
|
||||||
constexpr bool equal(T1 &&t1, T2 &&t2, Eq &&eq = {}) {
|
constexpr bool equal(T1&& t1, T2&& t2, Eq&& eq = {}) {
|
||||||
auto first1 = t1.begin();
|
auto first1 = t1.begin();
|
||||||
auto last1 = t1.end();
|
auto last1 = t1.end();
|
||||||
auto first2 = t2.begin();
|
auto first2 = t2.begin();
|
||||||
|
|
@ -63,7 +63,7 @@ constexpr bool equal(T1 &&t1, T2 &&t2, Eq &&eq = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Cmp = std::less<>, typename T1, typename T2>
|
template <typename Cmp = std::less<>, typename T1, typename T2>
|
||||||
constexpr bool lexicographical_compare(T1 &&t1, T2 &&t2, Cmp &&cmp = {}) noexcept {
|
constexpr bool lexicographical_compare(T1&& t1, T2&& t2, Cmp&& cmp = {}) noexcept {
|
||||||
auto first1 = t1.begin();
|
auto first1 = t1.begin();
|
||||||
auto last1 = t1.end();
|
auto last1 = t1.end();
|
||||||
auto first2 = t2.begin();
|
auto first2 = t2.begin();
|
||||||
|
|
@ -92,7 +92,7 @@ constexpr std::size_t popcount(T x) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Cmp = std::less<>, typename ForwardIt, typename E>
|
template <typename Cmp = std::less<>, typename ForwardIt, typename E>
|
||||||
constexpr ForwardIt lower_bound(ForwardIt first, ForwardIt last, E &&e, Cmp &&comp = {}) {
|
constexpr ForwardIt lower_bound(ForwardIt first, ForwardIt last, E&& e, Cmp&& comp = {}) {
|
||||||
auto count = std::distance(first, last);
|
auto count = std::distance(first, last);
|
||||||
|
|
||||||
for (auto it = first; count > 0;) {
|
for (auto it = first; count > 0;) {
|
||||||
|
|
@ -109,11 +109,9 @@ constexpr ForwardIt lower_bound(ForwardIt first, ForwardIt last, E &&e, Cmp &&co
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Cmp = std::less<>, typename BidirIt, typename E>
|
template <typename Cmp = std::less<>, typename BidirIt, typename E>
|
||||||
constexpr auto equal_range(BidirIt begin, BidirIt end, E &&e, Cmp &&comp = {}) {
|
constexpr auto equal_range(BidirIt begin, BidirIt end, E&& e, Cmp&& comp = {}) {
|
||||||
const auto first = lower_bound(begin, end, e, comp);
|
const auto first = lower_bound(begin, end, e, comp);
|
||||||
return std::pair{first, lower_bound(std::make_reverse_iterator(end), std::make_reverse_iterator(first), e, [&comp](auto &&lhs, auto &&rhs) {
|
return std::pair{first, lower_bound(std::make_reverse_iterator(end), std::make_reverse_iterator(first), e, [&comp](auto&& lhs, auto&& rhs) { return comp(rhs, lhs); }).base()};
|
||||||
return comp(rhs, lhs);
|
|
||||||
}).base()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E = void, typename Cmp = std::less<E>, typename = void>
|
template <typename E = void, typename Cmp = std::less<E>, typename = void>
|
||||||
|
|
@ -153,7 +151,7 @@ struct indexing {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static inline std::array<E, enum_count<E>()> values = get_indices().first;
|
constexpr static inline std::array<E, enum_count<E>()> values = get_indices().first;
|
||||||
constexpr static inline const std::array<E, enum_count<E>()> *values_v = &values;
|
constexpr static inline const std::array<E, enum_count<E>()>* values_v = &values;
|
||||||
constexpr static inline std::array<std::size_t, enum_count<E>()> reindex = get_indices().second;
|
constexpr static inline std::array<std::size_t, enum_count<E>()> reindex = get_indices().second;
|
||||||
|
|
||||||
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept {
|
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept {
|
||||||
|
|
@ -166,7 +164,7 @@ struct indexing {
|
||||||
|
|
||||||
template <typename E, typename Less>
|
template <typename E, typename Less>
|
||||||
struct indexing<E, Less, std::enable_if_t<std::is_enum_v<std::decay_t<E>> && (std::is_same_v<Less, std::less<E>> || std::is_same_v<Less, std::less<>>)>> {
|
struct indexing<E, Less, std::enable_if_t<std::is_enum_v<std::decay_t<E>> && (std::is_same_v<Less, std::less<E>> || std::is_same_v<Less, std::less<>>)>> {
|
||||||
constexpr static inline const std::array<E, enum_count<E>()> *values_v = &enum_values<E>();
|
constexpr static inline const std::array<E, enum_count<E>()>* values_v = &enum_values<E>();
|
||||||
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept { return enum_index(val); }
|
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept { return enum_index(val); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -235,18 +233,18 @@ struct FilteredIterator {
|
||||||
using iterator_category = std::bidirectional_iterator_tag;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
using value_type = std::remove_reference_t<std::invoke_result_t<Getter, Parent, Iterator>>;
|
using value_type = std::remove_reference_t<std::invoke_result_t<Getter, Parent, Iterator>>;
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
using pointer = value_type *;
|
using pointer = value_type*;
|
||||||
using reference = value_type &;
|
using reference = value_type&;
|
||||||
|
|
||||||
constexpr FilteredIterator() noexcept = default;
|
constexpr FilteredIterator() noexcept = default;
|
||||||
constexpr FilteredIterator(const FilteredIterator &) = default;
|
constexpr FilteredIterator(const FilteredIterator&) = default;
|
||||||
constexpr FilteredIterator &operator=(const FilteredIterator &) = default;
|
constexpr FilteredIterator& operator=(const FilteredIterator&) = default;
|
||||||
constexpr FilteredIterator(FilteredIterator &&) noexcept = default;
|
constexpr FilteredIterator(FilteredIterator&&) noexcept = default;
|
||||||
constexpr FilteredIterator &operator=(FilteredIterator &&) noexcept = default;
|
constexpr FilteredIterator& operator=(FilteredIterator&&) noexcept = default;
|
||||||
|
|
||||||
template <typename OtherParent, typename OtherIterator,
|
template <typename OtherParent, typename OtherIterator,
|
||||||
typename = std::enable_if_t<std::is_convertible_v<OtherParent, Parent> && std::is_convertible_v<OtherIterator, Iterator>> *>
|
typename = std::enable_if_t<std::is_convertible_v<OtherParent, Parent> && std::is_convertible_v<OtherIterator, Iterator>>*>
|
||||||
constexpr explicit FilteredIterator(const FilteredIterator<OtherParent, OtherIterator, Getter, Predicate> &other)
|
constexpr explicit FilteredIterator(const FilteredIterator<OtherParent, OtherIterator, Getter, Predicate>& other)
|
||||||
: parent(other.parent), first(other.first), last(other.last), current(other.current), getter(other.getter), predicate(other.predicate) {}
|
: parent(other.parent), first(other.first), last(other.last), current(other.current), getter(other.getter), predicate(other.predicate) {}
|
||||||
|
|
||||||
~FilteredIterator() = default;
|
~FilteredIterator() = default;
|
||||||
|
|
@ -262,7 +260,7 @@ struct FilteredIterator {
|
||||||
|
|
||||||
[[nodiscard]] constexpr pointer operator->() const { return std::addressof(**this); }
|
[[nodiscard]] constexpr pointer operator->() const { return std::addressof(**this); }
|
||||||
|
|
||||||
constexpr FilteredIterator &operator++() {
|
constexpr FilteredIterator& operator++() {
|
||||||
do {
|
do {
|
||||||
++current;
|
++current;
|
||||||
} while (current != last && !predicate(parent, current));
|
} while (current != last && !predicate(parent, current));
|
||||||
|
|
@ -275,7 +273,7 @@ struct FilteredIterator {
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr FilteredIterator &operator--() {
|
constexpr FilteredIterator& operator--() {
|
||||||
do {
|
do {
|
||||||
--current;
|
--current;
|
||||||
} while (current != first && !predicate(parent, current));
|
} while (current != first && !predicate(parent, current));
|
||||||
|
|
@ -288,9 +286,9 @@ struct FilteredIterator {
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const FilteredIterator &lhs, const FilteredIterator &rhs) { return lhs.current == rhs.current; }
|
[[nodiscard]] friend constexpr bool operator==(const FilteredIterator& lhs, const FilteredIterator& rhs) { return lhs.current == rhs.current; }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const FilteredIterator &lhs, const FilteredIterator &rhs) { return lhs.current != rhs.current; }
|
[[nodiscard]] friend constexpr bool operator!=(const FilteredIterator& lhs, const FilteredIterator& rhs) { return lhs.current != rhs.current; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
@ -393,13 +391,13 @@ struct array {
|
||||||
|
|
||||||
[[nodiscard]] constexpr size_type max_size() const noexcept { return a.max_size(); }
|
[[nodiscard]] constexpr size_type max_size() const noexcept { return a.max_size(); }
|
||||||
|
|
||||||
constexpr void fill(const V &value) {
|
constexpr void fill(const V& value) {
|
||||||
for (auto &v : a) {
|
for (auto& v : a) {
|
||||||
v = value;
|
v = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void swap(array &other) noexcept(std::is_nothrow_swappable_v<V>) {
|
constexpr void swap(array& other) noexcept(std::is_nothrow_swappable_v<V>) {
|
||||||
for (std::size_t i{}; i < a.size(); ++i) {
|
for (std::size_t i{}; i < a.size(); ++i) {
|
||||||
auto v = std::move(other.a[i]);
|
auto v = std::move(other.a[i]);
|
||||||
other.a[i] = std::move(a[i]);
|
other.a[i] = std::move(a[i]);
|
||||||
|
|
@ -407,24 +405,24 @@ struct array {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const array &a1, const array &a2) { return detail::equal(a1, a2); }
|
[[nodiscard]] friend constexpr bool operator==(const array& a1, const array& a2) { return detail::equal(a1, a2); }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const array &a1, const array &a2) { return !detail::equal(a1, a2); }
|
[[nodiscard]] friend constexpr bool operator!=(const array& a1, const array& a2) { return !detail::equal(a1, a2); }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator<(const array &a1, const array &a2) { return detail::lexicographical_compare(a1, a2); }
|
[[nodiscard]] friend constexpr bool operator<(const array& a1, const array& a2) { return detail::lexicographical_compare(a1, a2); }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator<=(const array &a1, const array &a2) { return !detail::lexicographical_compare(a2, a1); }
|
[[nodiscard]] friend constexpr bool operator<=(const array& a1, const array& a2) { return !detail::lexicographical_compare(a2, a1); }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator>(const array &a1, const array &a2) { return detail::lexicographical_compare(a2, a1); }
|
[[nodiscard]] friend constexpr bool operator>(const array& a1, const array& a2) { return detail::lexicographical_compare(a2, a1); }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator>=(const array &a1, const array &a2) { return !detail::lexicographical_compare(a1, a2); }
|
[[nodiscard]] friend constexpr bool operator>=(const array& a1, const array& a2) { return !detail::lexicographical_compare(a1, a2); }
|
||||||
|
|
||||||
container_type a;
|
container_type a;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename E, typename T, std::size_t N, std::size_t... I>
|
template <typename E, typename T, std::size_t N, std::size_t... I>
|
||||||
constexpr array<E, std::remove_cv_t<T>> to_array_impl(T (&a)[N], std::index_sequence<I...>) {
|
constexpr array<E, std::remove_cv_t<T>> to_array_impl(T (&a)[N], std::index_sequence<I...>) {
|
||||||
return {{a[I]...}};
|
return {{a[I]...}};
|
||||||
}
|
}
|
||||||
|
|
@ -447,7 +445,7 @@ constexpr std::enable_if_t<(enum_count<E>() == N), array<E, std::remove_cv_t<T>>
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E, typename... Ts>
|
template <typename E, typename... Ts>
|
||||||
constexpr std::enable_if_t<(enum_count<E>() == sizeof...(Ts)), array<E, std::remove_cv_t<std::common_type_t<Ts...>>>> make_array(Ts &&... ts) {
|
constexpr std::enable_if_t<(enum_count<E>() == sizeof...(Ts)), array<E, std::remove_cv_t<std::common_type_t<Ts...>>>> make_array(Ts&&... ts) {
|
||||||
return {{std::forward<Ts>(ts)...}};
|
return {{std::forward<Ts>(ts)...}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -472,7 +470,7 @@ class bitset {
|
||||||
constexpr static std::size_t not_interested = base_type_count * bits_per_base - enum_count<E>();
|
constexpr static std::size_t not_interested = base_type_count * bits_per_base - enum_count<E>();
|
||||||
constexpr static base_type last_value_max = (base_type{1} << (bits_per_base - not_interested)) - 1;
|
constexpr static base_type last_value_max = (base_type{1} << (bits_per_base - not_interested)) - 1;
|
||||||
|
|
||||||
template <typename parent_t = bitset *>
|
template <typename parent_t = bitset*>
|
||||||
class reference_impl {
|
class reference_impl {
|
||||||
friend class bitset;
|
friend class bitset;
|
||||||
|
|
||||||
|
|
@ -480,14 +478,12 @@ class bitset {
|
||||||
std::size_t num_index;
|
std::size_t num_index;
|
||||||
base_type bit_index;
|
base_type bit_index;
|
||||||
|
|
||||||
constexpr reference_impl(parent_t parent, std::size_t ix) noexcept
|
constexpr reference_impl(parent_t parent, std::size_t ix) noexcept : reference_impl(parent, std::pair{ix / bits_per_base, base_type{1} << (ix % bits_per_base)}) {}
|
||||||
: reference_impl(parent, std::pair{ix / bits_per_base, base_type{1} << (ix % bits_per_base)}) {}
|
|
||||||
|
|
||||||
constexpr reference_impl(parent_t parent, std::pair<std::size_t, base_type> ix) noexcept
|
constexpr reference_impl(parent_t parent, std::pair<std::size_t, base_type> ix) noexcept : parent(parent), num_index(std::get<0>(ix)), bit_index(std::get<1>(ix)) {}
|
||||||
: parent(parent), num_index(std::get<0>(ix)), bit_index(std::get<1>(ix)) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr reference_impl &operator=(bool v) noexcept {
|
constexpr reference_impl& operator=(bool v) noexcept {
|
||||||
if (v) {
|
if (v) {
|
||||||
parent->a[num_index] |= bit_index;
|
parent->a[num_index] |= bit_index;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -496,7 +492,7 @@ class bitset {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr reference_impl &operator=(const reference_impl &v) noexcept {
|
constexpr reference_impl& operator=(const reference_impl& v) noexcept {
|
||||||
if (this == &v) {
|
if (this == &v) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -508,7 +504,7 @@ class bitset {
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator~() const noexcept { return !static_cast<bool>(*this); }
|
[[nodiscard]] constexpr bool operator~() const noexcept { return !static_cast<bool>(*this); }
|
||||||
|
|
||||||
constexpr reference_impl &flip() noexcept {
|
constexpr reference_impl& flip() noexcept {
|
||||||
*this = ~*this;
|
*this = ~*this;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -529,11 +525,11 @@ class bitset {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using index_type = Index;
|
using index_type = Index;
|
||||||
using container_type = std::array<base_type, base_type_count>;
|
using container_type = std::array<base_type, base_type_count>;
|
||||||
using reference = reference_impl<>;
|
using reference = reference_impl<>;
|
||||||
using const_reference = reference_impl<const bitset *>;
|
using const_reference = reference_impl<const bitset*>;
|
||||||
|
|
||||||
constexpr explicit bitset(detail::raw_access_t = raw_access) noexcept : a{{}} {}
|
constexpr explicit bitset(detail::raw_access_t = raw_access) noexcept : a{{}} {}
|
||||||
|
|
||||||
|
|
@ -566,22 +562,21 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr explicit bitset(detail::raw_access_t, const char *str, std::size_t n = ~std::size_t{}, char zero = '0', char one = '1')
|
constexpr explicit bitset(detail::raw_access_t, const char* str, std::size_t n = ~std::size_t{}, char zero = '0', char one = '1')
|
||||||
: bitset(std::string_view{str, (std::min)(std::char_traits<char>::length(str), n)}, 0, n, zero, one) {}
|
: bitset(std::string_view{str, (std::min)(std::char_traits<char>::length(str), n)}, 0, n, zero, one) {}
|
||||||
|
|
||||||
constexpr bitset(std::initializer_list<E> starters) : a{{}} {
|
constexpr bitset(std::initializer_list<E> starters) : a{{}} {
|
||||||
if constexpr (magic_enum::detail::subtype_v<E> == magic_enum::detail::enum_subtype::flags) {
|
if constexpr (magic_enum::detail::subtype_v<E> == magic_enum::detail::enum_subtype::flags) {
|
||||||
for (auto &f : starters) {
|
for (auto& f : starters) {
|
||||||
*this |= bitset(f);
|
*this |= bitset(f);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto &f : starters) {
|
for (auto& f : starters) {
|
||||||
set(f);
|
set(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <class V,
|
template <typename V, std::enable_if_t<std::is_same_v<V, E> && magic_enum::detail::subtype_v<V> == magic_enum::detail::enum_subtype::flags, int> = 0>
|
||||||
std::enable_if_t<std::is_same_v<V, E> && magic_enum::detail::subtype_v<V> == magic_enum::detail::enum_subtype::flags, int> = 0>
|
|
||||||
constexpr explicit bitset(V starter) : a{{}} {
|
constexpr explicit bitset(V starter) : a{{}} {
|
||||||
auto u = enum_underlying(starter);
|
auto u = enum_underlying(starter);
|
||||||
for (E v : enum_values<E>()) {
|
for (E v : enum_values<E>()) {
|
||||||
|
|
@ -596,16 +591,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Cmp = std::equal_to<>>
|
template <typename Cmp = std::equal_to<>>
|
||||||
constexpr explicit bitset(string_view sv, Cmp &&cmp = {}, char sep = '|') {
|
constexpr explicit bitset(string_view sv, Cmp&& cmp = {}, char sep = '|') {
|
||||||
for (std::size_t to{}; (to = magic_enum::detail::find(sv, sep)) != string_view::npos; sv.remove_prefix(to + 1)) {
|
for (std::size_t to{}; (to = magic_enum::detail::find(sv, sep)) != string_view::npos; sv.remove_prefix(to + 1)) {
|
||||||
if (auto v = magic_enum::enum_cast<E>(sv.substr(0, to), cmp)) {
|
if (auto v = enum_cast<E>(sv.substr(0, to), cmp)) {
|
||||||
set(v);
|
set(v);
|
||||||
} else {
|
} else {
|
||||||
throw std::invalid_argument("enum bitset::constructor: unrecognized enum value in string");
|
throw std::invalid_argument("enum bitset::constructor: unrecognized enum value in string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!sv.empty()) {
|
if (!sv.empty()) {
|
||||||
if (auto v = magic_enum::enum_cast<E>(sv, cmp)) {
|
if (auto v = enum_cast<E>(sv, cmp)) {
|
||||||
set(v);
|
set(v);
|
||||||
} else {
|
} else {
|
||||||
throw std::invalid_argument("enum bitset::constructor: unrecognized enum value in string");
|
throw std::invalid_argument("enum bitset::constructor: unrecognized enum value in string");
|
||||||
|
|
@ -613,9 +608,9 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const bitset &lhs, const bitset &rhs) noexcept { return detail::equal(lhs.a, rhs.a); }
|
[[nodiscard]] friend constexpr bool operator==(const bitset& lhs, const bitset& rhs) noexcept { return detail::equal(lhs.a, rhs.a); }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator!=(const bitset &lhs, const bitset &rhs) noexcept { return !detail::equal(lhs.a, rhs.a); }
|
[[nodiscard]] friend constexpr bool operator!=(const bitset& lhs, const bitset& rhs) noexcept { return !detail::equal(lhs.a, rhs.a); }
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool operator[](E pos) const noexcept { return static_cast<bool>(const_reference(this, *index_type{}(pos))); }
|
[[nodiscard]] constexpr bool operator[](E pos) const noexcept { return static_cast<bool>(const_reference(this, *index_type{}(pos))); }
|
||||||
|
|
||||||
|
|
@ -646,7 +641,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool any() const noexcept {
|
[[nodiscard]] constexpr bool any() const noexcept {
|
||||||
for (auto &v : a) {
|
for (auto& v : a) {
|
||||||
if (v > 0) {
|
if (v > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -658,7 +653,7 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::size_t count() const noexcept {
|
[[nodiscard]] constexpr std::size_t count() const noexcept {
|
||||||
std::size_t c{};
|
std::size_t c{};
|
||||||
for (auto &v : a) {
|
for (auto& v : a) {
|
||||||
c += detail::popcount(v);
|
c += detail::popcount(v);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
|
|
@ -668,21 +663,21 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::size_t max_size() const noexcept { return enum_count<E>(); }
|
[[nodiscard]] constexpr std::size_t max_size() const noexcept { return enum_count<E>(); }
|
||||||
|
|
||||||
constexpr bitset &operator&=(const bitset &other) noexcept {
|
constexpr bitset& operator&=(const bitset& other) noexcept {
|
||||||
for (std::size_t i{}; i < base_type_count; ++i) {
|
for (std::size_t i{}; i < base_type_count; ++i) {
|
||||||
a[i] &= other.a[i];
|
a[i] &= other.a[i];
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bitset &operator|=(const bitset &other) noexcept {
|
constexpr bitset& operator|=(const bitset& other) noexcept {
|
||||||
for (std::size_t i{}; i < base_type_count; ++i) {
|
for (std::size_t i{}; i < base_type_count; ++i) {
|
||||||
a[i] |= other.a[i];
|
a[i] |= other.a[i];
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bitset &operator^=(const bitset &other) noexcept {
|
constexpr bitset& operator^=(const bitset& other) noexcept {
|
||||||
for (std::size_t i{}; i < base_type_count; ++i) {
|
for (std::size_t i{}; i < base_type_count; ++i) {
|
||||||
a[i] ^= other.a[i];
|
a[i] ^= other.a[i];
|
||||||
}
|
}
|
||||||
|
|
@ -701,7 +696,7 @@ public:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bitset &set() noexcept {
|
constexpr bitset& set() noexcept {
|
||||||
for (std::size_t i{}; i < base_type_count - (not_interested > 0); ++i) {
|
for (std::size_t i{}; i < base_type_count - (not_interested > 0); ++i) {
|
||||||
a[i] = ~base_type{};
|
a[i] = ~base_type{};
|
||||||
}
|
}
|
||||||
|
|
@ -712,7 +707,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bitset &set(E pos, bool value = true) {
|
constexpr bitset& set(E pos, bool value = true) {
|
||||||
if (auto ix = index_type{}(pos)) {
|
if (auto ix = index_type{}(pos)) {
|
||||||
reference{this, *ix} = value;
|
reference{this, *ix} = value;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -720,9 +715,9 @@ public:
|
||||||
throw std::out_of_range("enum bitset::set: unrecognized position");
|
throw std::out_of_range("enum bitset::set: unrecognized position");
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bitset &reset() noexcept { return *this = bitset{}; }
|
constexpr bitset& reset() noexcept { return *this = bitset{}; }
|
||||||
|
|
||||||
constexpr bitset &reset(E pos) {
|
constexpr bitset& reset(E pos) {
|
||||||
if (auto ix = index_type{}(pos)) {
|
if (auto ix = index_type{}(pos)) {
|
||||||
reference{this, *ix} = false;
|
reference{this, *ix} = false;
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -730,30 +725,30 @@ public:
|
||||||
throw std::out_of_range("enum bitset::reset: unrecognized position");
|
throw std::out_of_range("enum bitset::reset: unrecognized position");
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bitset &flip() noexcept { return *this = ~*this; }
|
constexpr bitset& flip() noexcept { return *this = ~*this; }
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bitset operator&(const bitset &lhs, const bitset &rhs) noexcept {
|
[[nodiscard]] friend constexpr bitset operator&(const bitset& lhs, const bitset& rhs) noexcept {
|
||||||
bitset cp = lhs;
|
bitset cp = lhs;
|
||||||
cp &= rhs;
|
cp &= rhs;
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bitset operator|(const bitset &lhs, const bitset &rhs) noexcept {
|
[[nodiscard]] friend constexpr bitset operator|(const bitset& lhs, const bitset& rhs) noexcept {
|
||||||
bitset cp = lhs;
|
bitset cp = lhs;
|
||||||
cp |= rhs;
|
cp |= rhs;
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bitset operator^(const bitset &lhs, const bitset &rhs) noexcept {
|
[[nodiscard]] friend constexpr bitset operator^(const bitset& lhs, const bitset& rhs) noexcept {
|
||||||
bitset cp = lhs;
|
bitset cp = lhs;
|
||||||
cp ^= rhs;
|
cp ^= rhs;
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename V = E>
|
template <typename V = E>
|
||||||
[[nodiscard]]constexpr explicit operator std::enable_if_t<magic_enum::detail::subtype_v<V> == magic_enum::detail::enum_subtype::flags, E>() const {
|
[[nodiscard]] constexpr explicit operator std::enable_if_t<magic_enum::detail::subtype_v<V> == magic_enum::detail::enum_subtype::flags, E>() const {
|
||||||
E res{};
|
E res{};
|
||||||
for (auto &e : enum_values<E>()) {
|
for (auto& e : enum_values<E>()) {
|
||||||
if (test(e)) {
|
if (test(e)) {
|
||||||
res |= e;
|
res |= e;
|
||||||
}
|
}
|
||||||
|
|
@ -764,7 +759,7 @@ public:
|
||||||
[[nodiscard]] string to_string(char sep = '|') const {
|
[[nodiscard]] string to_string(char sep = '|') const {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
for (auto &e : enum_values<E>()) {
|
for (auto& e : enum_values<E>()) {
|
||||||
if (test(e)) {
|
if (test(e)) {
|
||||||
if (!name.empty()) {
|
if (!name.empty()) {
|
||||||
name.append(1, sep);
|
name.append(1, sep);
|
||||||
|
|
@ -789,9 +784,9 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] constexpr unsigned long long to_ulong(detail::raw_access_t raw) const { return to_<unsigned long>(raw); }
|
[[nodiscard]] constexpr unsigned long long to_ulong(detail::raw_access_t raw) const { return to_<unsigned long>(raw); }
|
||||||
|
|
||||||
friend std::ostream &operator<<(std::ostream &o, const bitset &bs) { return o << bs.to_string(); }
|
friend std::ostream& operator<<(std::ostream& o, const bitset& bs) { return o << bs.to_string(); }
|
||||||
|
|
||||||
friend std::istream &operator>>(std::istream &i, bitset &bs) {
|
friend std::istream& operator>>(std::istream& i, bitset& bs) {
|
||||||
string s;
|
string s;
|
||||||
if (i >> s; !s.empty()) {
|
if (i >> s; !s.empty()) {
|
||||||
bs = bitset(string_view{s});
|
bs = bitset(string_view{s});
|
||||||
|
|
@ -799,11 +794,11 @@ public:
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
container_type a;
|
container_type a;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class V, int = 0>
|
template <typename V, int = 0>
|
||||||
explicit bitset(V starter) -> bitset<V>;
|
explicit bitset(V starter) -> bitset<V>;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -813,13 +808,13 @@ template <typename E, typename CExprLess = std::less<E>>
|
||||||
class set {
|
class set {
|
||||||
using index_type = detail::indexing<E, CExprLess>;
|
using index_type = detail::indexing<E, CExprLess>;
|
||||||
struct Getter {
|
struct Getter {
|
||||||
constexpr const E &operator()(const set *, const E *p) const noexcept { return *p; }
|
constexpr const E& operator()(const set*, const E* p) const noexcept { return *p; }
|
||||||
};
|
};
|
||||||
struct Predicate {
|
struct Predicate {
|
||||||
constexpr bool operator()(const set *h, const E *e) const noexcept { return h->a[*e]; }
|
constexpr bool operator()(const set* h, const E* e) const noexcept { return h->a[*e]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using container_type = bitset<E, index_type>;
|
using container_type = bitset<E, index_type>;
|
||||||
using key_type = E;
|
using key_type = E;
|
||||||
using value_type = E;
|
using value_type = E;
|
||||||
|
|
@ -827,12 +822,12 @@ public:
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
using key_compare = CExprLess;
|
using key_compare = CExprLess;
|
||||||
using value_compare = CExprLess;
|
using value_compare = CExprLess;
|
||||||
using reference = value_type &;
|
using reference = value_type&;
|
||||||
using const_reference = const value_type &;
|
using const_reference = const value_type&;
|
||||||
using pointer = value_type *;
|
using pointer = value_type*;
|
||||||
using const_pointer = const value_type *;
|
using const_pointer = const value_type*;
|
||||||
using iterator = detail::FilteredIterator<const set *, const E *, Getter, Predicate>;
|
using iterator = detail::FilteredIterator<const set*, const E*, Getter, Predicate>;
|
||||||
using const_iterator = detail::FilteredIterator<const set *, const E *, Getter, Predicate>;
|
using const_iterator = detail::FilteredIterator<const set*, const E*, Getter, Predicate>;
|
||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
|
@ -850,8 +845,7 @@ public:
|
||||||
insert(e);
|
insert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <class V,
|
template <typename V, std::enable_if_t<std::is_same_v<V, E> && magic_enum::detail::subtype_v<V> == magic_enum::detail::enum_subtype::flags, int> = 0>
|
||||||
std::enable_if_t<std::is_same_v<V, E> &&magic_enum::detail::subtype_v<V> == magic_enum::detail::enum_subtype::flags, int> = 0>
|
|
||||||
constexpr explicit set(V starter) {
|
constexpr explicit set(V starter) {
|
||||||
auto u = enum_underlying(starter);
|
auto u = enum_underlying(starter);
|
||||||
for (E v : enum_values<E>()) {
|
for (E v : enum_values<E>()) {
|
||||||
|
|
@ -861,12 +855,12 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr set(const set &) noexcept = default;
|
constexpr set(const set&) noexcept = default;
|
||||||
constexpr set(set &&) noexcept = default;
|
constexpr set(set&&) noexcept = default;
|
||||||
|
|
||||||
constexpr set &operator=(const set &) noexcept = default;
|
constexpr set& operator=(const set&) noexcept = default;
|
||||||
constexpr set &operator=(set &&) noexcept = default;
|
constexpr set& operator=(set&&) noexcept = default;
|
||||||
constexpr set &operator=(std::initializer_list<E> ilist) {
|
constexpr set& operator=(std::initializer_list<E> ilist) {
|
||||||
for (auto e : ilist) {
|
for (auto e : ilist) {
|
||||||
insert(e);
|
insert(e);
|
||||||
}
|
}
|
||||||
|
|
@ -903,7 +897,7 @@ public:
|
||||||
s = 0;
|
s = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::pair<iterator, bool> insert(const value_type &value) noexcept {
|
constexpr std::pair<iterator, bool> insert(const value_type& value) noexcept {
|
||||||
if (auto i = index_type{}(value)) {
|
if (auto i = index_type{}(value)) {
|
||||||
typename container_type::reference ref = a[value];
|
typename container_type::reference ref = a[value];
|
||||||
bool r = !ref;
|
bool r = !ref;
|
||||||
|
|
@ -917,11 +911,11 @@ public:
|
||||||
return {end(), false};
|
return {end(), false};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr std::pair<iterator, bool> insert(value_type &&value) noexcept { return insert(value); }
|
constexpr std::pair<iterator, bool> insert(value_type&& value) noexcept { return insert(value); }
|
||||||
|
|
||||||
constexpr iterator insert(const_iterator, const value_type &value) noexcept { return insert(value).first; }
|
constexpr iterator insert(const_iterator, const value_type& value) noexcept { return insert(value).first; }
|
||||||
|
|
||||||
constexpr iterator insert(const_iterator hint, value_type &&value) noexcept { return insert(hint, value); }
|
constexpr iterator insert(const_iterator hint, value_type&& value) noexcept { return insert(hint, value); }
|
||||||
|
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
constexpr void insert(InputIt first, InputIt last) noexcept {
|
constexpr void insert(InputIt first, InputIt last) noexcept {
|
||||||
|
|
@ -937,10 +931,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
constexpr std::pair<iterator, bool> emplace(Args &&... args) noexcept { return insert({std::forward<Args>(args)...}); }
|
constexpr std::pair<iterator, bool> emplace(Args&&... args) noexcept {
|
||||||
|
return insert({std::forward<Args>(args)...});
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
constexpr iterator emplace_hint(const_iterator, Args &&... args) noexcept { return emplace(std::forward<Args>(args)...).first; }
|
constexpr iterator emplace_hint(const_iterator, Args&&... args) noexcept {
|
||||||
|
return emplace(std::forward<Args>(args)...).first;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr iterator erase(const_iterator pos) noexcept {
|
constexpr iterator erase(const_iterator pos) noexcept {
|
||||||
erase(*pos++);
|
erase(*pos++);
|
||||||
|
|
@ -954,7 +952,7 @@ public:
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_type erase(const key_type &key) noexcept {
|
constexpr size_type erase(const key_type& key) noexcept {
|
||||||
typename container_type::reference ref = a[key];
|
typename container_type::reference ref = a[key];
|
||||||
bool res = ref;
|
bool res = ref;
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|
@ -965,7 +963,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
constexpr std::enable_if_t<detail::is_transparent_v<KC>, size_type> erase(K &&x) noexcept {
|
constexpr std::enable_if_t<detail::is_transparent_v<KC>, size_type> erase(K&& x) noexcept {
|
||||||
size_type c{};
|
size_type c{};
|
||||||
for (auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{}); first != last;) {
|
for (auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{}); first != last;) {
|
||||||
c += erase(*first++);
|
c += erase(*first++);
|
||||||
|
|
@ -973,16 +971,16 @@ public:
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(set &other) noexcept {
|
void swap(set& other) noexcept {
|
||||||
set cp = *this;
|
set cp = *this;
|
||||||
*this = other;
|
*this = other;
|
||||||
other = cp;
|
other = cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr size_type count(const key_type &key) const noexcept { return index_type{}(key) && a[key]; }
|
[[nodiscard]] constexpr size_type count(const key_type& key) const noexcept { return index_type{}(key) && a[key]; }
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, size_type> count(const K &x) const {
|
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, size_type> count(const K& x) const {
|
||||||
size_type c{};
|
size_type c{};
|
||||||
for (auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{}); first != last; ++first) {
|
for (auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{}); first != last; ++first) {
|
||||||
c += count(*first);
|
c += count(*first);
|
||||||
|
|
@ -990,14 +988,14 @@ public:
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr const_iterator find(const key_type &key) const noexcept {
|
[[nodiscard]] constexpr const_iterator find(const key_type& key) const noexcept {
|
||||||
if (auto i = index_type{}(key); i && a.test(key))
|
if (auto i = index_type{}(key); i && a.test(key))
|
||||||
return const_iterator{this, index_type::values_v->begin(), index_type::values_v->end(), &(*index_type::values_v)[*i]};
|
return const_iterator{this, index_type::values_v->begin(), index_type::values_v->end(), &(*index_type::values_v)[*i]};
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, const_iterator> find(const K &x) const {
|
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, const_iterator> find(const K& x) const {
|
||||||
for (auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{}); first != last; ++first) {
|
for (auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{}); first != last; ++first) {
|
||||||
if (a.test(*first)) {
|
if (a.test(*first)) {
|
||||||
return find(*first);
|
return find(*first);
|
||||||
|
|
@ -1006,23 +1004,21 @@ public:
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool contains(const key_type &key) const noexcept { return count(key); }
|
[[nodiscard]] constexpr bool contains(const key_type& key) const noexcept { return count(key); }
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, bool> contains(const K &x) const noexcept {
|
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, bool> contains(const K& x) const noexcept {
|
||||||
return count(x) > 0;
|
return count(x) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const noexcept {
|
[[nodiscard]] constexpr std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const noexcept { return {lower_bound(key), upper_bound(key)}; }
|
||||||
return {lower_bound(key), upper_bound(key)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, std::pair<const_iterator, const_iterator>> equal_range(const K &x) const noexcept {
|
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, std::pair<const_iterator, const_iterator>> equal_range(const K& x) const noexcept {
|
||||||
return {lower_bound(x), upper_bound(x)};
|
return {lower_bound(x), upper_bound(x)};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr const_iterator lower_bound(const key_type &key) const noexcept {
|
[[nodiscard]] constexpr const_iterator lower_bound(const key_type& key) const noexcept {
|
||||||
if (auto i = index_type{}(key)) {
|
if (auto i = index_type{}(key)) {
|
||||||
auto it = const_iterator{this, index_type::values_v->begin(), index_type::values_v->end(), &(*index_type::values_v)[*i]};
|
auto it = const_iterator{this, index_type::values_v->begin(), index_type::values_v->end(), &(*index_type::values_v)[*i]};
|
||||||
return a.test(key) ? it : std::next(it);
|
return a.test(key) ? it : std::next(it);
|
||||||
|
|
@ -1031,12 +1027,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, const_iterator> lower_bound(const K &x) const noexcept {
|
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, const_iterator> lower_bound(const K& x) const noexcept {
|
||||||
auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{});
|
auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{});
|
||||||
return first != last ? lower_bound(*first) : end();
|
return first != last ? lower_bound(*first) : end();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr const_iterator upper_bound(const key_type &key) const noexcept {
|
[[nodiscard]] constexpr const_iterator upper_bound(const key_type& key) const noexcept {
|
||||||
if (auto i = index_type{}(key)) {
|
if (auto i = index_type{}(key)) {
|
||||||
return std::next(const_iterator{this, index_type::values_v->begin(), index_type::values_v->end(), &(*index_type::values_v)[*i]});
|
return std::next(const_iterator{this, index_type::values_v->begin(), index_type::values_v->end(), &(*index_type::values_v)[*i]});
|
||||||
}
|
}
|
||||||
|
|
@ -1044,7 +1040,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename KC = key_compare>
|
template <typename K, typename KC = key_compare>
|
||||||
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, const_iterator> upper_bound(const K &x) const noexcept {
|
[[nodiscard]] constexpr std::enable_if_t<detail::is_transparent_v<KC>, const_iterator> upper_bound(const K& x) const noexcept {
|
||||||
auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{});
|
auto [first, last] = detail::equal_range(index_type::values_v->begin(), index_type::values_v->end(), x, key_compare{});
|
||||||
return first != last ? upper_bound(*std::prev(last)) : end();
|
return first != last ? upper_bound(*std::prev(last)) : end();
|
||||||
}
|
}
|
||||||
|
|
@ -1053,11 +1049,11 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] constexpr value_compare value_comp() const { return {}; }
|
[[nodiscard]] constexpr value_compare value_comp() const { return {}; }
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator==(const set &lhs, const set &rhs) noexcept { return lhs.a == rhs.a; }
|
[[nodiscard]] constexpr friend bool operator==(const set& lhs, const set& rhs) noexcept { return lhs.a == rhs.a; }
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator!=(const set &lhs, const set &rhs) noexcept { return lhs.a != rhs.a; }
|
[[nodiscard]] constexpr friend bool operator!=(const set& lhs, const set& rhs) noexcept { return lhs.a != rhs.a; }
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator<(const set &lhs, const set &rhs) noexcept {
|
[[nodiscard]] constexpr friend bool operator<(const set& lhs, const set& rhs) noexcept {
|
||||||
if (lhs.s < rhs.s) {
|
if (lhs.s < rhs.s) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1065,7 +1061,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &e : *index_type::values_v) {
|
for (auto& e : *index_type::values_v) {
|
||||||
if (auto c = rhs.contains(e); c != lhs.contains(e)) {
|
if (auto c = rhs.contains(e); c != lhs.contains(e)) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
@ -1073,11 +1069,11 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator<=(const set &lhs, const set &rhs) noexcept { return !(rhs < lhs); }
|
[[nodiscard]] constexpr friend bool operator<=(const set& lhs, const set& rhs) noexcept { return !(rhs < lhs); }
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator>(const set &lhs, const set &rhs) noexcept { return rhs < lhs; }
|
[[nodiscard]] constexpr friend bool operator>(const set& lhs, const set& rhs) noexcept { return rhs < lhs; }
|
||||||
|
|
||||||
[[nodiscard]] constexpr friend bool operator>=(const set &lhs, const set &rhs) noexcept { return !(lhs < rhs); }
|
[[nodiscard]] constexpr friend bool operator>=(const set& lhs, const set& rhs) noexcept { return !(lhs < rhs); }
|
||||||
|
|
||||||
template <typename Pred>
|
template <typename Pred>
|
||||||
size_type erase_if(Pred pred) {
|
size_type erase_if(Pred pred) {
|
||||||
|
|
@ -1093,13 +1089,12 @@ public:
|
||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
|
|
||||||
private:
|
private:
|
||||||
container_type a;
|
container_type a;
|
||||||
std::size_t s{};
|
std::size_t s{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename V, int = 0>
|
||||||
template <class V, int = 0>
|
|
||||||
explicit set(V starter) -> set<V>;
|
explicit set(V starter) -> set<V>;
|
||||||
|
|
||||||
} // namespace magic_enum::containers
|
} // namespace magic_enum::containers
|
||||||
|
|
@ -1107,50 +1102,42 @@ explicit set(V starter) -> set<V>;
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
template <auto I, typename E, typename V, typename Index>
|
template <auto I, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), V &>
|
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), V&> get(magic_enum::containers::array<E, V, Index>& a) noexcept {
|
||||||
get(magic_enum::containers::array<E, V, Index> &a) noexcept {
|
|
||||||
return a.a[I];
|
return a.a[I];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto I, typename E, typename V, typename Index>
|
template <auto I, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), V &&>
|
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), V&&> get(magic_enum::containers::array<E, V, Index>&& a) noexcept {
|
||||||
get(magic_enum::containers::array<E, V, Index> &&a) noexcept {
|
|
||||||
return std::move(a.a[I]);
|
return std::move(a.a[I]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto I, typename E, typename V, typename Index>
|
template <auto I, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), const V &>
|
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), const V&> get(const magic_enum::containers::array<E, V, Index>& a) noexcept {
|
||||||
get(const magic_enum::containers::array<E, V, Index> &a) noexcept {
|
|
||||||
return a.a[I];
|
return a.a[I];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto I, typename E, typename V, typename Index>
|
template <auto I, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), const V &&>
|
constexpr std::enable_if_t<(std::is_integral_v<decltype(I)> && I < magic_enum::enum_count<E>()), const V&&> get(const magic_enum::containers::array<E, V, Index>&& a) noexcept {
|
||||||
get(const magic_enum::containers::array<E, V, Index> &&a) noexcept {
|
|
||||||
return std::move(a.a[I]);
|
return std::move(a.a[I]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto Enum, typename E, typename V, typename Index>
|
template <auto Enum, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), V &>
|
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), V&> get(magic_enum::containers::array<E, V, Index>& a) noexcept {
|
||||||
get(magic_enum::containers::array<E, V, Index> &a) noexcept {
|
|
||||||
return a[Enum];
|
return a[Enum];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto Enum, typename E, typename V, typename Index>
|
template <auto Enum, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), V &&>
|
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), V&&> get(magic_enum::containers::array<E, V, Index>&& a) noexcept {
|
||||||
get(magic_enum::containers::array<E, V, Index> &&a) noexcept {
|
|
||||||
return std::move(a[Enum]);
|
return std::move(a[Enum]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto Enum, typename E, typename V, typename Index>
|
template <auto Enum, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), const V &>
|
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), const V&> get(const magic_enum::containers::array<E, V, Index>& a) noexcept {
|
||||||
get(const magic_enum::containers::array<E, V, Index> &a) noexcept {
|
|
||||||
return a[Enum];
|
return a[Enum];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <auto Enum, typename E, typename V, typename Index>
|
template <auto Enum, typename E, typename V, typename Index>
|
||||||
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), const V &&>
|
constexpr std::enable_if_t<std::is_same_v<decltype(Enum), E> && magic_enum::enum_contains(Enum), const V&&> get(const magic_enum::containers::array<E, V, Index>&& a) noexcept {
|
||||||
get(const magic_enum::containers::array<E, V, Index> &&a) noexcept {
|
|
||||||
return std::move(a[Enum]);
|
return std::move(a[Enum]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
// Copyright (c) 2019 - 2023 Daniil Goncharov <neargye@gmail.com>.
|
||||||
|
// Copyright (c) 2022 - 2023 Bela Schaum <schaumb@gmail.com>.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue