mirror of
https://github.com/Neargye/magic_enum.git
synced 2026-01-10 23:44:29 +00:00
fix _ITERATOR_DEBUG_LEVEL
This commit is contained in:
parent
e43f7a9329
commit
fd9f70b91d
3 changed files with 94 additions and 77 deletions
|
|
@ -26,10 +26,6 @@
|
||||||
# pragma warning(disable : 4244) // warning C4244: 'argument': conversion from 'const T' to 'unsigned int', possible loss of data.
|
# pragma warning(disable : 4244) // warning C4244: 'argument': conversion from 'const T' to 'unsigned int', possible loss of data.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define _ITERATOR_DEBUG_LEVEL 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <magic_enum_containers.hpp>
|
#include <magic_enum_containers.hpp>
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,10 @@ namespace magic_enum::containers {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
[[maybe_unused]] constexpr static bool is_transparent_v{};
|
static constexpr bool is_transparent_v{};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr static bool is_transparent_v<T, std::void_t<typename T::is_transparent>>{true};
|
static constexpr 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 = {}) {
|
||||||
|
|
@ -100,7 +100,6 @@ 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;) {
|
||||||
auto step = count / 2;
|
auto step = count / 2;
|
||||||
std::advance(it, step);
|
std::advance(it, step);
|
||||||
|
|
@ -121,8 +120,8 @@ constexpr auto equal_range(BidirIt begin, BidirIt end, E&& e, Cmp&& comp = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename E = void, typename Cmp = std::less<E>, typename = void>
|
template <typename E = void, typename Cmp = std::less<E>, typename = void>
|
||||||
struct indexing {
|
class indexing {
|
||||||
[[nodiscard]] constexpr static auto get_indices() noexcept {
|
[[nodiscard]] static constexpr auto get_indices() noexcept {
|
||||||
// reverse result index mapping
|
// reverse result index mapping
|
||||||
std::array<std::size_t, enum_count<E>()> rev_res{};
|
std::array<std::size_t, enum_count<E>()> rev_res{};
|
||||||
|
|
||||||
|
|
@ -156,37 +155,66 @@ struct indexing {
|
||||||
return std::pair{sorted_values, res};
|
return std::pair{sorted_values, res};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr static inline std::array<E, enum_count<E>()> values = get_indices().first;
|
static constexpr auto indices = get_indices();
|
||||||
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;
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept {
|
public:
|
||||||
|
static constexpr auto& values = indices.first;
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr const E* begin() noexcept {
|
||||||
|
return values.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr const E* end() noexcept {
|
||||||
|
return values.data() + values.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr optional<std::size_t> at(E val) noexcept {
|
||||||
if (auto opt = enum_index(val)) {
|
if (auto opt = enum_index(val)) {
|
||||||
return reindex[*opt];
|
return indices.second[*opt];
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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<>>)>> {
|
class 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>();
|
public:
|
||||||
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept { return enum_index(val); }
|
static constexpr auto& values = enum_values<E>();
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr const E* begin() noexcept {
|
||||||
|
return values.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr const E* end() noexcept {
|
||||||
|
return values.data() + values.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] static constexpr optional<std::size_t> at(E val) noexcept { return enum_index(val); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Less>
|
template <typename Less>
|
||||||
struct indexing<void, Less, void> {
|
struct indexing<void, Less, void> {
|
||||||
using is_transparent = std::true_type;
|
using is_transparent = std::true_type;
|
||||||
|
|
||||||
template <typename E>
|
template <typename E>
|
||||||
[[nodiscard]] constexpr inline optional<std::size_t> operator()(E val) const noexcept {
|
[[nodiscard]] static constexpr const E* begin() noexcept {
|
||||||
constexpr indexing<E, Less> ix{};
|
return indexing<E, Less>::begin();
|
||||||
return ix(val);
|
}
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
[[nodiscard]] static constexpr const E* end() noexcept {
|
||||||
|
return indexing<E, Less>::end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
[[nodiscard]] constexpr optional<std::size_t> at(E val) noexcept {
|
||||||
|
return indexing<E, Less>::at(val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename E = void, typename OP = std::less<>, typename = void>
|
template <typename E = void, typename OP = std::less<>, typename = void>
|
||||||
struct name_sort_impl {
|
struct name_sort_impl {
|
||||||
[[nodiscard]] constexpr inline bool operator()(E e1, E e2) const noexcept { return OP{}(enum_name(e1), enum_name(e2)); }
|
[[nodiscard]] constexpr bool operator()(E e1, E e2) const noexcept { return OP{}(enum_name(e1), enum_name(e2)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename OP>
|
template <typename OP>
|
||||||
|
|
@ -197,18 +225,17 @@ struct name_sort_impl<void, OP> {
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
struct FullCmp<S, std::enable_if_t<!std::is_invocable_v<S, string_view, string_view> && std::is_invocable_v<S, char_type, char_type>>> {
|
struct FullCmp<S, std::enable_if_t<!std::is_invocable_v<S, string_view, string_view> && std::is_invocable_v<S, char_type, char_type>>> {
|
||||||
[[nodiscard]] constexpr inline bool operator()(string_view s1, string_view s2) const noexcept { return lexicographical_compare<S>(s1, s2); }
|
[[nodiscard]] constexpr bool operator()(string_view s1, string_view s2) const noexcept { return lexicographical_compare<S>(s1, s2); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename E1, typename E2>
|
template <typename E1, typename E2>
|
||||||
[[nodiscard]] constexpr inline std::enable_if_t<
|
[[nodiscard]] constexpr std::enable_if_t<
|
||||||
// at least one of need to be an enum type
|
// at least one of need to be an enum type
|
||||||
(std::is_enum_v<std::decay_t<E1>> || std::is_enum_v<std::decay_t<E2>>)&&
|
(std::is_enum_v<std::decay_t<E1>> || std::is_enum_v<std::decay_t<E2>>) &&
|
||||||
// if both is enum, only accept if the same enum
|
// if both is enum, only accept if the same enum
|
||||||
(!std::is_enum_v<std::decay_t<E1>> || !std::is_enum_v<std::decay_t<E2>> || std::is_same_v<E1, E2>)&&
|
(!std::is_enum_v<std::decay_t<E1>> || !std::is_enum_v<std::decay_t<E2>> || std::is_same_v<E1, E2>) &&
|
||||||
// is invocable with comparator
|
// is invocable with comparator
|
||||||
(std::is_invocable_r_v<bool, FullCmp<>, std::conditional_t<std::is_enum_v<std::decay_t<E1>>, string_view, E1>,
|
(std::is_invocable_r_v<bool, FullCmp<>, std::conditional_t<std::is_enum_v<std::decay_t<E1>>, string_view, E1>, std::conditional_t<std::is_enum_v<std::decay_t<E2>>, string_view, E2>>),
|
||||||
std::conditional_t<std::is_enum_v<std::decay_t<E2>>, string_view, E2>>),
|
|
||||||
bool>
|
bool>
|
||||||
operator()(E1 e1, E2 e2) const noexcept {
|
operator()(E1 e1, E2 e2) const noexcept {
|
||||||
using D1 = std::decay_t<E1>;
|
using D1 = std::decay_t<E1>;
|
||||||
|
|
@ -248,13 +275,10 @@ struct FilteredIterator {
|
||||||
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;
|
|
||||||
|
|
||||||
constexpr FilteredIterator(Parent p, Iterator begin, Iterator end, Iterator curr, Getter getter = {}, Predicate pred = {})
|
constexpr FilteredIterator(Parent p, Iterator begin, Iterator end, Iterator curr, Getter getter = {}, Predicate pred = {})
|
||||||
: parent(p), first(std::move(begin)), last(std::move(end)), current(std::move(curr)), getter{std::move(getter)}, predicate{std::move(pred)} {
|
: parent(p), first(std::move(begin)), last(std::move(end)), current(std::move(curr)), getter{std::move(getter)}, predicate{std::move(pred)} {
|
||||||
if (current == first && !predicate(parent, current)) {
|
if (current == first && !predicate(parent, current)) {
|
||||||
|
|
@ -300,18 +324,20 @@ struct FilteredIterator {
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename E = void>
|
template <typename E = void>
|
||||||
using name_less [[maybe_unused]] = detail::name_sort_impl<E>;
|
using name_less = detail::name_sort_impl<E>;
|
||||||
template <typename E = void>
|
|
||||||
using name_greater [[maybe_unused]] = detail::name_sort_impl<E, std::greater<>>;
|
|
||||||
|
|
||||||
using name_less_ci [[maybe_unused]] = detail::name_sort_impl<void, magic_enum::detail::case_insensitive<std::less<>>>;
|
template <typename E = void>
|
||||||
using name_greater_ci [[maybe_unused]] = detail::name_sort_impl<void, magic_enum::detail::case_insensitive<std::greater<>>>;
|
using name_greater = detail::name_sort_impl<E, std::greater<>>;
|
||||||
|
|
||||||
|
using name_less_case_insensitive = detail::name_sort_impl<void, magic_enum::detail::case_insensitive<std::less<>>>;
|
||||||
|
|
||||||
|
using name_greater_case_insensitive = detail::name_sort_impl<void, magic_enum::detail::case_insensitive<std::greater<>>>;
|
||||||
|
|
||||||
template <typename E = void>
|
template <typename E = void>
|
||||||
using default_indexing = detail::indexing<E>;
|
using default_indexing = detail::indexing<E>;
|
||||||
|
|
||||||
template <typename Cmp = std::less<>>
|
template <typename Cmp = std::less<>>
|
||||||
using comparator_indexing [[maybe_unused]] = detail::indexing<void, Cmp>;
|
using comparator_indexing = detail::indexing<void, Cmp>;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// ARRAY //
|
// ARRAY //
|
||||||
|
|
@ -320,7 +346,7 @@ template <typename E, typename V, typename Index = default_indexing<E>>
|
||||||
struct array {
|
struct array {
|
||||||
static_assert(std::is_enum_v<E>);
|
static_assert(std::is_enum_v<E>);
|
||||||
static_assert(std::is_trivially_constructible_v<Index>);
|
static_assert(std::is_trivially_constructible_v<Index>);
|
||||||
static_assert(enum_count<E>() == 0 || Index{}(enum_values<E>().front())); // check Index is constexpr
|
static_assert(enum_count<E>() == 0 || Index::at(enum_values<E>().front())); // check Index is constexpr
|
||||||
|
|
||||||
using index_type = Index;
|
using index_type = Index;
|
||||||
using container_type = std::array<V, enum_count<E>()>;
|
using container_type = std::array<V, enum_count<E>()>;
|
||||||
|
|
@ -338,22 +364,22 @@ struct array {
|
||||||
using const_reverse_iterator = typename container_type::const_reverse_iterator;
|
using const_reverse_iterator = typename container_type::const_reverse_iterator;
|
||||||
|
|
||||||
constexpr reference at(E pos) {
|
constexpr reference at(E pos) {
|
||||||
if (auto index = index_type{}(pos)) {
|
if (auto index = index_type::at(pos)) {
|
||||||
return a[*index];
|
return a[*index];
|
||||||
}
|
}
|
||||||
MAGIC_ENUM_THROW(std::out_of_range("enum array::at: unrecognized position"));
|
MAGIC_ENUM_THROW(std::out_of_range("enum array::at: unrecognized position"));
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_reference at(E pos) const {
|
constexpr const_reference at(E pos) const {
|
||||||
if (auto index = index_type{}(pos)) {
|
if (auto index = index_type::at(pos)) {
|
||||||
return a[*index];
|
return a[*index];
|
||||||
}
|
}
|
||||||
MAGIC_ENUM_THROW(std::out_of_range("enum array::at: unrecognized position"));
|
MAGIC_ENUM_THROW(std::out_of_range("enum array::at: unrecognized position"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr reference operator[](E pos) noexcept { return a[*index_type{}(pos)]; }
|
[[nodiscard]] constexpr reference operator[](E pos) { return a[*index_type::at(pos)]; }
|
||||||
|
|
||||||
[[nodiscard]] constexpr const_reference operator[](E pos) const noexcept { return a[*index_type{}(pos)]; }
|
[[nodiscard]] constexpr const_reference operator[](E pos) const { return a[*index_type::at(pos)]; }
|
||||||
|
|
||||||
[[nodiscard]] constexpr reference front() noexcept { return a.front(); }
|
[[nodiscard]] constexpr reference front() noexcept { return a.front(); }
|
||||||
|
|
||||||
|
|
@ -464,17 +490,17 @@ template <typename E, typename Index = default_indexing<E>>
|
||||||
class bitset {
|
class bitset {
|
||||||
static_assert(std::is_enum_v<E>);
|
static_assert(std::is_enum_v<E>);
|
||||||
static_assert(std::is_trivially_constructible_v<Index>);
|
static_assert(std::is_trivially_constructible_v<Index>);
|
||||||
static_assert(enum_count<E>() == 0 || Index{}(enum_values<E>().front())); // check Index is constexpr
|
static_assert(enum_count<E>() == 0 || Index::at(enum_values<E>().front())); // check Index is constexpr
|
||||||
|
|
||||||
using base_type = std::conditional_t<enum_count<E>() <= 8, std::uint_least8_t,
|
using base_type = std::conditional_t<enum_count<E>() <= 8, std::uint_least8_t,
|
||||||
std::conditional_t<enum_count<E>() <= 16, std::uint_least16_t,
|
std::conditional_t<enum_count<E>() <= 16, std::uint_least16_t,
|
||||||
std::conditional_t<enum_count<E>() <= 32, std::uint_least32_t,
|
std::conditional_t<enum_count<E>() <= 32, std::uint_least32_t,
|
||||||
std::uint_least64_t>>>;
|
std::uint_least64_t>>>;
|
||||||
|
|
||||||
constexpr static std::size_t bits_per_base = sizeof(base_type) * 8;
|
static constexpr std::size_t bits_per_base = sizeof(base_type) * 8;
|
||||||
constexpr static std::size_t base_type_count = (enum_count<E>() > 0 ? (enum_count<E>() - 1) / bits_per_base + 1 : 0);
|
static constexpr std::size_t base_type_count = (enum_count<E>() > 0 ? (enum_count<E>() - 1) / bits_per_base + 1 : 0);
|
||||||
constexpr static std::size_t not_interested = base_type_count * bits_per_base - enum_count<E>();
|
static constexpr 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;
|
static constexpr 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 {
|
||||||
|
|
@ -618,12 +644,12 @@ class bitset {
|
||||||
|
|
||||||
[[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 { return static_cast<bool>(const_reference(this, *index_type::at(pos))); }
|
||||||
|
|
||||||
[[nodiscard]] constexpr reference operator[](E pos) noexcept { return reference{this, *index_type{}(pos)}; }
|
[[nodiscard]] constexpr reference operator[](E pos) { return reference{this, *index_type::at(pos)}; }
|
||||||
|
|
||||||
constexpr bool test(E pos) const {
|
constexpr bool test(E pos) const {
|
||||||
if (auto ix = index_type{}(pos)) {
|
if (auto ix = index_type::at(pos)) {
|
||||||
return static_cast<bool>(const_reference(this, *ix));
|
return static_cast<bool>(const_reference(this, *ix));
|
||||||
}
|
}
|
||||||
MAGIC_ENUM_THROW(std::out_of_range("enum bitset::test: unrecognized position"));
|
MAGIC_ENUM_THROW(std::out_of_range("enum bitset::test: unrecognized position"));
|
||||||
|
|
@ -714,7 +740,7 @@ class bitset {
|
||||||
}
|
}
|
||||||
|
|
||||||
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::at(pos)) {
|
||||||
reference{this, *ix} = value;
|
reference{this, *ix} = value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -724,7 +750,7 @@ class bitset {
|
||||||
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::at(pos)) {
|
||||||
reference{this, *ix} = false;
|
reference{this, *ix} = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -754,7 +780,7 @@ class bitset {
|
||||||
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 (const auto& e : enum_values<E>()) {
|
||||||
if (test(e)) {
|
if (test(e)) {
|
||||||
res |= e;
|
res |= e;
|
||||||
}
|
}
|
||||||
|
|
@ -765,7 +791,7 @@ class bitset {
|
||||||
[[nodiscard]] string to_string(char_type sep = static_cast<char_type>('|')) const {
|
[[nodiscard]] string to_string(char_type sep = static_cast<char_type>('|')) const {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
for (auto& e : enum_values<E>()) {
|
for (const 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);
|
||||||
|
|
@ -873,11 +899,11 @@ class set {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_iterator begin() const noexcept {
|
constexpr const_iterator begin() const noexcept {
|
||||||
return const_iterator{this, &(*index_type::values_v->begin()), &(*index_type::values_v->end()), &(*index_type::values_v->begin())};
|
return const_iterator{this, index_type::begin(), index_type::end(), index_type::begin()};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_iterator end() const noexcept {
|
constexpr const_iterator end() const noexcept {
|
||||||
return const_iterator{this, &(*index_type::values_v->begin()), &(*index_type::values_v->end()), &(*index_type::values_v->end())};
|
return const_iterator{this, index_type::begin(), index_type::end(), index_type::end()};
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const_iterator cbegin() const noexcept { return begin(); }
|
constexpr const_iterator cbegin() const noexcept { return begin(); }
|
||||||
|
|
@ -904,7 +930,7 @@ class set {
|
||||||
}
|
}
|
||||||
|
|
||||||
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::at(value)) {
|
||||||
typename container_type::reference ref = a[value];
|
typename container_type::reference ref = a[value];
|
||||||
bool r = !ref;
|
bool r = !ref;
|
||||||
if (r) {
|
if (r) {
|
||||||
|
|
@ -912,7 +938,7 @@ class set {
|
||||||
++s;
|
++s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {iterator{this, &(*index_type::values_v->begin()), &(*index_type::values_v->end()), &(*index_type::values_v)[*i]}, r};
|
return {iterator{this, index_type::begin(), index_type::end(), &(index_type::values[*i])}, r};
|
||||||
}
|
}
|
||||||
return {end(), false};
|
return {end(), false};
|
||||||
}
|
}
|
||||||
|
|
@ -953,7 +979,6 @@ class set {
|
||||||
|
|
||||||
constexpr iterator erase(const_iterator first, const_iterator last) noexcept {
|
constexpr iterator erase(const_iterator first, const_iterator last) noexcept {
|
||||||
while ((first = erase(first)) != last) {
|
while ((first = erase(first)) != last) {
|
||||||
;
|
|
||||||
}
|
}
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
@ -971,7 +996,7 @@ class set {
|
||||||
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 = 0;
|
size_type c = 0;
|
||||||
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::begin(), index_type::end(), x, key_compare{}); first != last;) {
|
||||||
c += erase(*first++);
|
c += erase(*first++);
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
|
|
@ -983,26 +1008,27 @@ class set {
|
||||||
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::at(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 = 0;
|
size_type c = 0;
|
||||||
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::begin(), index_type::end(), x, key_compare{}); first != last; ++first) {
|
||||||
c += count(*first);
|
c += count(*first);
|
||||||
}
|
}
|
||||||
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::at(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::begin(), index_type::end(), &(index_type::values[*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::begin(), index_type::end(), x, key_compare{}); first != last; ++first) {
|
||||||
if (a.test(*first)) {
|
if (a.test(*first)) {
|
||||||
return find(*first);
|
return find(*first);
|
||||||
}
|
}
|
||||||
|
|
@ -1025,8 +1051,8 @@ class set {
|
||||||
}
|
}
|
||||||
|
|
||||||
[[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::at(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::begin(), index_type::end(), &(index_type::values[*i])};
|
||||||
return a.test(key) ? it : std::next(it);
|
return a.test(key) ? it : std::next(it);
|
||||||
}
|
}
|
||||||
return end();
|
return end();
|
||||||
|
|
@ -1034,20 +1060,20 @@ class set {
|
||||||
|
|
||||||
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::begin(), index_type::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::at(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::begin(), index_type::end(), &(index_type::values[*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> 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::begin(), index_type::end(), x, key_compare{});
|
||||||
return first != last ? upper_bound(*std::prev(last)) : end();
|
return first != last ? upper_bound(*std::prev(last)) : end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1067,7 +1093,7 @@ class set {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& e : *index_type::values_v) {
|
for (auto& e : index_type::values) {
|
||||||
if (auto c = rhs.contains(e); c != lhs.contains(e)) {
|
if (auto c = rhs.contains(e); c != lhs.contains(e)) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
@ -1093,7 +1119,6 @@ class set {
|
||||||
}
|
}
|
||||||
return old_size - size();
|
return old_size - size();
|
||||||
}
|
}
|
||||||
//...
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
container_type a;
|
container_type a;
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,6 @@
|
||||||
# pragma warning(disable : 4244) // warning C4244: 'argument': conversion from 'const T' to 'unsigned int', possible loss of data.
|
# pragma warning(disable : 4244) // warning C4244: 'argument': conversion from 'const T' to 'unsigned int', possible loss of data.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define _ITERATOR_DEBUG_LEVEL 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CATCH_CONFIG_MAIN
|
#define CATCH_CONFIG_MAIN
|
||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue