Simplify some C++ abstractions (#1518)

* Remove namespaces
* Prefer `bool operator==`, not `friend auto operator==`
* Prefer not to use `using`
* Use a `constexpr` function instead of a template for `flipTable`
This commit is contained in:
Sylvie
2024-09-26 00:07:27 -04:00
committed by GitHub
parent 8037b9e10a
commit 9783671399
11 changed files with 80 additions and 124 deletions

View File

@@ -6,52 +6,46 @@
#include <tuple>
#include <utility>
template<typename T>
class EnumSeqIterator {
T _value;
public:
explicit EnumSeqIterator(T value) : _value(value) {}
EnumSeqIterator &operator++() {
_value = (T)(_value + 1);
return *this;
}
auto operator*() const { return _value; }
friend auto operator==(EnumSeqIterator const &lhs, EnumSeqIterator const &rhs) {
return lhs._value == rhs._value;
}
friend auto operator!=(EnumSeqIterator const &lhs, EnumSeqIterator const &rhs) {
return lhs._value != rhs._value;
}
};
template<typename T>
class EnumSeq {
T _start;
T _stop;
class Iterator {
T _value;
public:
explicit Iterator(T value) : _value(value) {}
Iterator &operator++() {
_value = (T)(_value + 1);
return *this;
}
auto operator*() const { return _value; }
bool operator==(Iterator const &rhs) const { return _value == rhs._value; }
bool operator!=(Iterator const &rhs) const { return _value != rhs._value; }
};
public:
explicit EnumSeq(T stop) : _start((T)0), _stop(stop) {}
explicit EnumSeq(T start, T stop) : _start(start), _stop(stop) {}
EnumSeqIterator<T> begin() { return EnumSeqIterator(_start); }
EnumSeqIterator<T> end() { return EnumSeqIterator(_stop); }
Iterator begin() { return Iterator(_start); }
Iterator end() { return Iterator(_stop); }
};
// This is not a fully generic implementation; its current use cases only require for-loop behavior.
// We also assume that all iterators have the same length.
template<typename... Iters>
class Zip {
std::tuple<Iters...> _iters;
template<typename... Ts>
class ZipIterator {
std::tuple<Ts...> _iters;
public:
explicit Zip(std::tuple<Iters...> &&iters) : _iters(iters) {}
explicit ZipIterator(std::tuple<Ts...> &&iters) : _iters(iters) {}
Zip &operator++() {
ZipIterator &operator++() {
std::apply([](auto &&...it) { (++it, ...); }, _iters);
return *this;
}
@@ -62,26 +56,24 @@ public:
);
}
friend auto operator==(Zip const &lhs, Zip const &rhs) {
return std::get<0>(lhs._iters) == std::get<0>(rhs._iters);
bool operator==(ZipIterator const &rhs) const {
return std::get<0>(_iters) == std::get<0>(rhs._iters);
}
friend auto operator!=(Zip const &lhs, Zip const &rhs) {
return std::get<0>(lhs._iters) != std::get<0>(rhs._iters);
bool operator!=(ZipIterator const &rhs) const {
return std::get<0>(_iters) != std::get<0>(rhs._iters);
}
};
namespace detail {
template<typename... Containers>
template<typename... Ts>
class ZipContainer {
std::tuple<Containers...> _containers;
std::tuple<Ts...> _containers;
public:
explicit ZipContainer(Containers &&...containers)
: _containers(std::forward<Containers>(containers)...) {}
explicit ZipContainer(Ts &&...containers) : _containers(std::forward<Ts>(containers)...) {}
auto begin() {
return Zip(std::apply(
return ZipIterator(std::apply(
[](auto &&...containers) {
using std::begin;
return std::make_tuple(begin(containers)...);
@@ -91,7 +83,7 @@ public:
}
auto end() {
return Zip(std::apply(
return ZipIterator(std::apply(
[](auto &&...containers) {
using std::end;
return std::make_tuple(end(containers)...);
@@ -105,12 +97,11 @@ public:
template<typename T>
using Holder = std::
conditional_t<std::is_lvalue_reference_v<T>, T, std::remove_cv_t<std::remove_reference_t<T>>>;
} // namespace detail
// Does the same number of iterations as the first container's iterator!
template<typename... Containers>
static constexpr auto zip(Containers &&...cs) {
return detail::ZipContainer<detail::Holder<Containers>...>(std::forward<Containers>(cs)...);
template<typename... Ts>
static constexpr auto zip(Ts &&...cs) {
return ZipContainer<Holder<Ts>...>(std::forward<Ts>(cs)...);
}
#endif // RGBDS_ITERTOOLS_HPP