mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-23 03:22:08 +00:00
Use an iterator zip
Simplifies iterating over tiles and attributes at the same time
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
* Allocator adaptor that interposes construct() calls to convert value-initialization
|
||||
* (which is what you get with e.g. `vector::resize`) into default-initialization (which does not
|
||||
* zero out non-class types).
|
||||
* From https://stackoverflow.com/questions/21028299/is-this-behavior-of-vectorresizesize-type-n-under-c11-and-boost-container/21028912#21028912
|
||||
* From
|
||||
* https://stackoverflow.com/questions/21028299/is-this-behavior-of-vectorresizesize-type-n-under-c11-and-boost-container/21028912#21028912
|
||||
*/
|
||||
|
||||
#ifndef DEFAULT_INIT_ALLOC_H
|
||||
@@ -23,11 +24,11 @@ public:
|
||||
using A::A; // Inherit the allocator's constructors
|
||||
|
||||
template<typename U>
|
||||
void construct(U * ptr) noexcept(std::is_nothrow_default_constructible_v<U>) {
|
||||
::new(static_cast<void *>(ptr)) U;
|
||||
void construct(U *ptr) noexcept(std::is_nothrow_default_constructible_v<U>) {
|
||||
::new (static_cast<void *>(ptr)) U;
|
||||
}
|
||||
template<typename U, typename... Args>
|
||||
void construct(U * ptr, Args && ... args) {
|
||||
void construct(U *ptr, Args &&...args) {
|
||||
a_t::construct(static_cast<A &>(*this), ptr, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
90
include/itertools.hpp
Normal file
90
include/itertools.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2022, Eldred Habert and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ITERTOOLS_HPP
|
||||
#define RGBDS_ITERTOOLS_HPP
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
template<typename... Ts>
|
||||
static inline void report() {
|
||||
puts(__PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
public:
|
||||
explicit Zip(std::tuple<Iters...> &&iters) : _iters(iters) {}
|
||||
|
||||
Zip &operator++() {
|
||||
std::apply([](auto &&...it) { (++it, ...); }, _iters);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator*() const {
|
||||
return std::apply([](auto &&...it) { return std::tuple<decltype(*it)...>(*it...); },
|
||||
_iters);
|
||||
}
|
||||
|
||||
friend auto operator==(Zip const &lhs, Zip const &rhs) {
|
||||
return std::get<0>(lhs._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);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename... Containers>
|
||||
class ZipContainer {
|
||||
std::tuple<Containers...> _containers;
|
||||
|
||||
public:
|
||||
ZipContainer(Containers &&...containers)
|
||||
: _containers(std::forward<Containers>(containers)...) {}
|
||||
|
||||
auto begin() {
|
||||
return Zip(std::apply(
|
||||
[](auto &&...containers) {
|
||||
using std::begin;
|
||||
return std::make_tuple(begin(containers)...);
|
||||
},
|
||||
_containers));
|
||||
}
|
||||
|
||||
auto end() {
|
||||
return Zip(std::apply(
|
||||
[](auto &&...containers) {
|
||||
using std::end;
|
||||
return std::make_tuple(end(containers)...);
|
||||
},
|
||||
_containers));
|
||||
}
|
||||
};
|
||||
|
||||
// Take ownership of objects and rvalue refs passed to us, but not lvalue refs
|
||||
template<typename T>
|
||||
using Holder = std::conditional_t<std::is_lvalue_reference_v<T>, T,
|
||||
std::remove_cv_t<std::remove_reference_t<T>>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)...);
|
||||
}
|
||||
|
||||
#endif /* RGBDS_ITERTOOLS_HPP */
|
||||
Reference in New Issue
Block a user