[libvmake] add vmake::zip()

This commit is contained in:
方而静 2023-07-23 16:28:39 +08:00
parent 2ac908690f
commit 785d40e578
2 changed files with 68 additions and 1 deletions

View File

@ -0,0 +1,9 @@
#include "../vmake.hpp"
using namespace std;
int main() {
vmake::outputln(cout, " ", vmake::transform(vmake::zip(vmake::range(1, 10)
, vmake::range(2, 10, 2)), [](const auto &x) {
return std::get<0>(x) + std::get<1>(x);
}));
}

View File

@ -523,7 +523,7 @@ struct grouper {
} }
}; };
} } // namespace details
template<size_t n, typename Gen> template<size_t n, typename Gen>
inline auto group(Gen &&g) { inline auto group(Gen &&g) {
@ -536,6 +536,64 @@ inline decltype(auto) discard_n(Gen &&g, size_t n) {
return std::forward<Gen>(g); return std::forward<Gen>(g);
} }
namespace details {
template<typename Gen, size_t ...index>
auto zipper_call_helper(Gen &&g, std::index_sequence<index...>) {
return std::make_tuple(std::get<index>(g)()...);
}
inline constexpr bool zip_terminate_helper() noexcept {
return false;
}
template<typename Seq, typename ...Seqs>
inline bool zip_terminate_helper(Seq& f, Seqs& ...rest) noexcept {
if (f.is_terminated()) return true;
return zip_terminate_helper(rest...);
}
template<typename Tuple, size_t ...index>
inline auto zip_terminate_applier(Tuple &t, std::index_sequence<index...>) noexcept {
return polyfill::apply(zip_terminate_helper<
typename std::tuple_element<index, Tuple>::type...>, t);
}
template<typename Gen>
struct zipper {
private:
static constexpr auto _n = std::tuple_size<Gen>::value;
using _make_index = std::make_index_sequence<_n>;
public:
using result = decltype(zipper_call_helper(std::declval<Gen>(), _make_index()));
using core = Gen;
Gen g;
zipper(zipper<Gen> &&) = default;
zipper(const zipper<Gen> &) = default;
zipper(Gen &&g) : g(std::forward<Gen>(g)) {}
bool is_terminated() const noexcept {
return zip_terminate_applier(g, _make_index());
}
decltype(auto) operator()() {
return zipper_call_helper(g, _make_index());
}
};
} // namespace detail
template<typename ...Gen>
inline decltype(auto) zip(Gen&&... g) {
using Tuple = std::tuple<typename std::decay<Gen>::type...>;
return details::zipper<Tuple>(std::make_tuple(std::forward<Gen>(g)...));
}
namespace rng { namespace rng {
inline auto make_seed() { inline auto make_seed() {