util/FilteredContainer: new class
This commit is contained in:
parent
9210705598
commit
f6a687dc2b
|
@ -0,0 +1,116 @@
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
// author: Max Kellermann <max.kellermann@gmail.com>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iterator> // for std::iterator_traits
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A container wrapper which returns only elements for which a second
|
||||||
|
* container returns true.
|
||||||
|
*/
|
||||||
|
template<std::input_iterator AB, typename AE,
|
||||||
|
std::input_iterator BB>
|
||||||
|
class FilteredContainer {
|
||||||
|
[[no_unique_address]]
|
||||||
|
AB a_begin;
|
||||||
|
|
||||||
|
[[no_unique_address]]
|
||||||
|
AE a_end;
|
||||||
|
|
||||||
|
[[no_unique_address]]
|
||||||
|
BB b_begin;
|
||||||
|
|
||||||
|
struct end_iterator {
|
||||||
|
using Traits = std::iterator_traits<AE>;
|
||||||
|
|
||||||
|
using iterator_category = typename Traits::iterator_category;
|
||||||
|
using difference_type = typename Traits::difference_type;
|
||||||
|
using value_type = typename Traits::value_type;
|
||||||
|
using pointer = typename Traits::pointer;
|
||||||
|
using reference = typename Traits::reference;
|
||||||
|
|
||||||
|
AE a;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit constexpr FilteredContainer(AB _a_begin, AE _a_end, BB _b_begin) noexcept
|
||||||
|
:a_begin(_a_begin), a_end(_a_end), b_begin(_b_begin) {}
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
using Traits = std::iterator_traits<AB>;
|
||||||
|
|
||||||
|
[[no_unique_address]]
|
||||||
|
AB a;
|
||||||
|
|
||||||
|
[[no_unique_address]]
|
||||||
|
AE a_end;
|
||||||
|
|
||||||
|
[[no_unique_address]]
|
||||||
|
BB b;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator_category = typename std::forward_iterator_tag;
|
||||||
|
using difference_type = typename Traits::difference_type;
|
||||||
|
using value_type = typename Traits::value_type;
|
||||||
|
using pointer = typename Traits::pointer;
|
||||||
|
using reference = typename Traits::reference;
|
||||||
|
|
||||||
|
explicit constexpr iterator(AB _a, AE _a_end, BB _b) noexcept
|
||||||
|
:a(_a), a_end(_a_end), b(_b) {}
|
||||||
|
|
||||||
|
constexpr void FindEnabled() noexcept {
|
||||||
|
while (a != a_end && !*b) {
|
||||||
|
++a;
|
||||||
|
++b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const iterator &other) const noexcept {
|
||||||
|
return a == other.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(const end_iterator &other) const noexcept {
|
||||||
|
return a == other.a;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto &operator++() noexcept {
|
||||||
|
++a;
|
||||||
|
++b;
|
||||||
|
FindEnabled();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto operator++(int) noexcept {
|
||||||
|
auto old = *this;
|
||||||
|
++*this;
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const noexcept {
|
||||||
|
return a.operator*();
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer operator->() const noexcept {
|
||||||
|
return a.operator->();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr iterator begin() const noexcept {
|
||||||
|
iterator it{a_begin, a_end, b_begin};
|
||||||
|
it.FindEnabled();
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr end_iterator end() const noexcept {
|
||||||
|
return {a_end};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator cbegin() const noexcept {
|
||||||
|
return begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr end_iterator cend() const noexcept {
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue