-
Notifications
You must be signed in to change notification settings - Fork 298
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: towards plain struct flavor entities (#3216)
Step towards removing the array backing in the flavor entity classes. This systematically removes all usage of operator[] so that the array backing can be deleted in a followup. This is achieved by having a pointer_view method that is defined in const and non-const forms (cleanest way I could find was through a simple macro) and returns an array of each pointer. Pointers were used over references to not have to deal with references decaying into values. Happy to take feedback on the approach, it isn't cleaning up much just yet, but will make way for a followup PR that removes the backing arrays. Also: - Adds a zip_view class that aims to get us using zip_view before C++2023 fully lands. I yoinked some open source and slimmed it down a bit for what we're likely to use. --------- Co-authored-by: ludamad <[email protected]>
- Loading branch information
Showing
18 changed files
with
737 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
#pragma once | ||
/* ********************************* FILE ************************************/ | ||
/** \file mzip.hpp | ||
* | ||
* \brief This header contains the zip iterator class. | ||
* | ||
* WARNING this is a zip view, not a zip copy! | ||
* | ||
* \remark | ||
* - c++17 | ||
* - no dependencies | ||
* - header only | ||
* - tested by test_zip_iterator.cpp | ||
* - not thread safe | ||
* - view ! | ||
* - extends lifetime of rvalue inputs untill the end of the for loop | ||
* | ||
* \todo | ||
* - add algorithm tests, probably does not work at all... | ||
* | ||
* | ||
* \example | ||
* std::vector<int> as{1,2},bs{1,2,3}; | ||
* for(auto [index, a,b]: zip(as,bs)){ | ||
* a++; | ||
* } | ||
* cout<<as<<endl; // shows (2, 3) | ||
* works for any number | ||
* | ||
* zip returns tuples of references to the contents | ||
* | ||
* | ||
* | ||
* | ||
* | ||
* | ||
* | ||
* | ||
* | ||
* does not copy the containers | ||
* returns tuple of references to the containers content | ||
* iterates untill the first iterator hits end. | ||
* extends ownership to the end of the for loop, or untill zip goes out of scope. | ||
* | ||
* possibly risky behaviour on clang, gcc for fun(const zip& z) when called as fun(zip(a,b)) | ||
* | ||
* | ||
* Depends on the following behaviour for for loops: | ||
* | ||
* // in for(x:zip) | ||
* // equiv: | ||
* { // c++ 11+ | ||
* auto && __range = range_expression ; | ||
* for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { | ||
* range_declaration = *__begin; | ||
* loop_statement | ||
* } | ||
* } | ||
* | ||
* { // in c++ 17 | ||
* auto && __range = range_expression ; | ||
* auto __begin = begin_expr ; | ||
* auto __end = end_expr ; | ||
* for ( ; __begin != __end; ++__begin) { | ||
* range_declaration = *__begin; | ||
* loop_statement | ||
* } | ||
* } | ||
* | ||
* | ||
* \author Mikael Persson | ||
* \date 2019-09-01 | ||
******************************************************************************/ | ||
|
||
static_assert(__cplusplus >= 201703L, | ||
" must be c++17 or greater"); // could be rewritten in c++11, but the features you must use will be buggy | ||
// in an older compiler anyways. | ||
#include <cassert> | ||
#include <functional> | ||
#include <iostream> | ||
#include <sstream> | ||
#include <tuple> | ||
#include <type_traits> | ||
#include <vector> | ||
|
||
template <class T> | ||
/** | ||
* @brief The zip_iterator class | ||
* | ||
* Provides a zip iterator which is at end when any is at end | ||
*/ | ||
class zip_iterator { | ||
public: | ||
// speeds up compilation a little bit... | ||
using tuple_indexes = std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>; | ||
|
||
zip_iterator(T iter, T iter_end) | ||
: iter(iter) | ||
, iter_end(iter_end) | ||
{} | ||
// prefix, inc first, then return | ||
zip_iterator& operator++() | ||
{ | ||
for_each_in_tuple([](auto&& x) { return x++; }, iter); | ||
// then if any hit end, update all to point to end. | ||
auto end = apply2([](auto x, auto y) { return x == y; }, iter, iter_end); | ||
if (if_any_in(end)) { | ||
apply2([](auto& x, auto y) { return x = y; }, iter, iter_end); | ||
} | ||
index++; | ||
return *this; | ||
} | ||
// sufficient because ++ keeps track and sets all to end when any is | ||
bool operator!=(const zip_iterator& other) const { return other.iter != iter; } | ||
auto operator*() const | ||
{ | ||
return std::forward<decltype(get_refs(iter, tuple_indexes{}))>(get_refs(iter, tuple_indexes{})); | ||
} | ||
|
||
private: | ||
T iter, iter_end; | ||
std::size_t index = 0; | ||
|
||
template <std::size_t... I> auto get_refs(T t, std::index_sequence<I...>) const | ||
{ | ||
return std::make_tuple(std::ref(*std::get<I>(t))...); | ||
} | ||
|
||
template <class F, class A, std::size_t... I> auto apply2_impl(F&& f, A&& a, A&& b, std::index_sequence<I...>) | ||
{ | ||
return std::make_tuple(f(std::get<I>(a), std::get<I>(b))...); | ||
} | ||
template <class F, class A> auto apply2(F&& f, A&& a, A&& b) | ||
{ | ||
return apply2_impl(std::forward<F>(f), std::forward<A>(a), std::forward<A>(b), tuple_indexes{}); | ||
} | ||
template <class A, std::size_t... I> bool if_any_impl(const A& t, std::index_sequence<I...>) const | ||
{ | ||
return (... || std::get<I>(t)); // c++17 | ||
} | ||
|
||
// in general context we must enforce that these are tuples | ||
template <class A> bool if_any_in(A&& t) const { return if_any_impl(std::forward<A>(t), tuple_indexes{}); } | ||
|
||
template <class F, class Tuple, std::size_t... I> | ||
auto for_each_in_impl(F&& f, Tuple&& t, std::index_sequence<I...>) const | ||
{ | ||
return std::make_tuple(f(std::get<I>(t))...); | ||
} | ||
|
||
template <class F, class A> void for_each_in_tuple(F&& f, A&& t) const | ||
{ | ||
for_each_in_impl(std::forward<F>(f), std::forward<A>(t), tuple_indexes{}); | ||
} | ||
}; | ||
|
||
template <class... S> class zip_view { | ||
using arg_indexes = std::make_index_sequence<sizeof...(S)>; | ||
|
||
public: | ||
zip_view(S... args) | ||
: args(std::forward<S>(args)...) | ||
{} | ||
auto begin() const { return get_begins(arg_indexes{}); } | ||
auto end() const { return get_ends(arg_indexes{}); } | ||
[[nodiscard]] std::size_t size() const { return size_impl(arg_indexes{}); } | ||
|
||
private: | ||
std::tuple<S...> args; | ||
template <std::size_t... I> auto get_begins(std::index_sequence<I...>) const | ||
{ | ||
return zip_iterator(std::make_tuple(std::get<I>(args).begin()...), std::make_tuple(std::get<I>(args).end()...)); | ||
} | ||
template <std::size_t... I> auto get_ends(std::index_sequence<I...>) const | ||
{ | ||
return zip_iterator(std::make_tuple(std::get<I>(args).end()...), std::make_tuple(std::get<I>(args).end()...)); | ||
} | ||
template <std::size_t... I> auto size_impl(std::index_sequence<I...>) const | ||
{ | ||
return std::max({ std::size_t(std::get<I>(args).size())... }); | ||
} | ||
|
||
template <class A, std::size_t... I> bool if_any_impl(const A& t, std::index_sequence<I...>) const | ||
{ | ||
return (... || std::get<I>(t)); // c++17 | ||
} | ||
}; | ||
|
||
// deduction guide, | ||
template <class... S> zip_view(S&&...) -> zip_view<S...>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.