Utils and tuple changes
This commit is contained in:
parent
285ae2137f
commit
956c3bfa05
2 changed files with 101 additions and 23 deletions
|
@ -23,7 +23,10 @@ struct TupleHelper<std::index_sequence<Is...>, Ts...> : public TupleLeaf<Is, Ts>
|
||||||
inline constexpr TupleHelper(TTs&&... args) :
|
inline constexpr TupleHelper(TTs&&... args) :
|
||||||
TupleLeaf<Is, Ts>{std::forward<TTs>(args)}... {};
|
TupleLeaf<Is, Ts>{std::forward<TTs>(args)}... {};
|
||||||
inline constexpr TupleHelper(const TupleHelper&) = default;
|
inline constexpr TupleHelper(const TupleHelper&) = default;
|
||||||
|
inline constexpr TupleHelper(TupleHelper&) = default;
|
||||||
inline constexpr TupleHelper(TupleHelper&&) = default;
|
inline constexpr TupleHelper(TupleHelper&&) = default;
|
||||||
|
inline constexpr TupleHelper() :
|
||||||
|
TupleLeaf<Is, Ts>{}... {};
|
||||||
inline constexpr bool operator==(const TupleHelper&) const = default;
|
inline constexpr bool operator==(const TupleHelper&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,7 +67,9 @@ struct Tuple : public impl::TupleHelper<std::index_sequence_for<Ts...>, Ts...> {
|
||||||
impl::TupleHelper<std::index_sequence_for<Ts...>, Ts...>(std::move(args)...) {};
|
impl::TupleHelper<std::index_sequence_for<Ts...>, Ts...>(std::move(args)...) {};
|
||||||
inline constexpr Tuple(const Tuple&) = default;
|
inline constexpr Tuple(const Tuple&) = default;
|
||||||
inline constexpr Tuple(Tuple&&) = default;
|
inline constexpr Tuple(Tuple&&) = default;
|
||||||
|
inline constexpr Tuple(Tuple&) = default;
|
||||||
|
inline constexpr Tuple() requires (sizeof...(Ts) != 0) :
|
||||||
|
impl::TupleHelper<std::index_sequence_for<Ts...>, Ts...>() {};
|
||||||
template <typename... TTs>
|
template <typename... TTs>
|
||||||
inline constexpr bool operator==(const Tuple<TTs...>& other) const
|
inline constexpr bool operator==(const Tuple<TTs...>& other) const
|
||||||
requires (TypeList<Ts...>{} == TypeList<TTs...>{}) {
|
requires (TypeList<Ts...>{} == TypeList<TTs...>{}) {
|
||||||
|
|
|
@ -111,41 +111,114 @@ inline constexpr auto Reverse(Tuple&& tuple) {
|
||||||
}(std::make_index_sequence<kTupleSize<Tuple>>());
|
}(std::make_index_sequence<kTupleSize<Tuple>>());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace impl {
|
||||||
|
|
||||||
|
template <typename...>
|
||||||
|
struct LeftFold;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct LeftFold<T> {
|
||||||
|
T data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename F>
|
||||||
|
struct LeftFold<T, F> {
|
||||||
|
T data;
|
||||||
|
const F& f;
|
||||||
|
template <typename TT>
|
||||||
|
inline constexpr auto operator|(LeftFold<TT>&& other) {
|
||||||
|
using R = decltype(f(std::move(this->data), std::move(other.data)));
|
||||||
|
return LeftFold<R, F>{.data = f(std::move(this->data), std::move(other.data)), .f = this->f};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace impl
|
||||||
|
|
||||||
|
|
||||||
|
template <TupleLike Tuple, typename T, typename F>
|
||||||
|
inline constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f) {
|
||||||
|
return [&]<auto... Is>(std::index_sequence<Is...>){
|
||||||
|
return (
|
||||||
|
impl::LeftFold<std::remove_cvref_t<T>, std::remove_cvref_t<F>>{.data = std::forward<T>(init), .f = std::forward<F>(f)}
|
||||||
|
| ...
|
||||||
|
| impl::LeftFold<std::remove_cvref_t<decltype(Get<Is>(tuple))>>{.data = Get<Is>(tuple)}
|
||||||
|
).data;
|
||||||
|
}(std::make_index_sequence<kTupleSize<Tuple>>());
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <TupleLike Tuple, TupleLike Tuple2>
|
template <TupleLike Tuple, TupleLike Tuple2>
|
||||||
inline constexpr auto TupleCat(Tuple&& tuple, Tuple2&& tuple2) {
|
inline constexpr auto TupleCat(Tuple&& tuple, Tuple2&& tuple2) {
|
||||||
return [&]<auto... Is, auto... IIs>(std::index_sequence<Is...>, std::index_sequence<IIs...>){
|
return [&]<auto... Is, auto... IIs>(std::index_sequence<Is...>, std::index_sequence<IIs...>){
|
||||||
return MakeTuple<Tuple>(Get<Is>(tuple)..., Get<IIs>(tuple2)...);
|
return MakeTuple<Tuple>(Get<Is>(tuple)..., Get<IIs>(tuple2)...);
|
||||||
}(std::make_index_sequence<kTupleSize<Tuple>>(), std::make_index_sequence<kTupleSize<Tuple2>>());
|
}(std::make_index_sequence<kTupleSize<Tuple>>(), std::make_index_sequence<kTupleSize<Tuple2>>());
|
||||||
};
|
};
|
||||||
namespace impl {
|
|
||||||
template <TupleLike Tuple>
|
|
||||||
struct TupleCater {
|
|
||||||
Tuple tuple;
|
|
||||||
template <TupleLike Other>
|
|
||||||
inline constexpr auto operator+(TupleCater<Other>&& other) {
|
|
||||||
using ResultType = decltype(TupleCat(std::move(this->tuple), other.tuple));
|
|
||||||
return TupleCater<ResultType>{TupleCat(std::move(this->tuple), std::move(other.tuple))};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} // namespace impl
|
|
||||||
|
|
||||||
template <TupleLike... Tuples>
|
template <TupleLike... Tuples>
|
||||||
inline constexpr auto TupleCat(Tuples&&... tuples) {
|
inline constexpr auto TupleCat(Tuples&&... tuples) requires (sizeof...(tuples) >= 1) {
|
||||||
return (impl::TupleCater{std::forward<Tuples>(tuples)} + ...).tuple;
|
return LeftFold(
|
||||||
|
Tuple{std::forward<Tuples>(tuples)...},
|
||||||
|
MakeTuple<decltype(Arg<0>(std::forward<Tuples>(tuples)...))>(),
|
||||||
|
[]<TupleLike Tup, TupleLike Tup2>(Tup&& tup, Tup2&& tup2){
|
||||||
|
return TupleCat(std::forward<Tup>(tup), std::forward<Tup2>(tup2));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
template <typename... Ts>
|
||||||
|
inline constexpr auto Tie(Ts&... args) -> Tuple<Ts&...> {
|
||||||
|
return {args...};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename...> typename F, TupleLike Tuple>
|
||||||
|
inline constexpr bool kEveryElement =
|
||||||
|
[]<auto... Is>(std::index_sequence<Is...>){
|
||||||
|
return (F<decltype(Get<Is>(std::declval<Tuple>()))>::value && ...);
|
||||||
|
}(std::make_index_sequence<kTupleSize<Tuple>>());
|
||||||
|
|
||||||
|
template <template <typename...> typename F, typename... Ts>
|
||||||
|
struct PartialCaller {
|
||||||
|
template <typename... TTs>
|
||||||
|
using type = F<Ts..., TTs...>;
|
||||||
|
};
|
||||||
|
template <template <typename...> typename F, typename... Ts>
|
||||||
|
consteval auto PartialCallerF(TypeList<Ts...>) {
|
||||||
|
return []<typename... TTs>(TypeList<TTs...>){
|
||||||
|
return F<Ts..., TTs...>{};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <TupleLike Tuple, typename T>
|
||||||
|
inline constexpr auto FirstOf(Tuple&& tuple, T&& init) requires kEveryElement<std::is_invocable, Tuple> {
|
||||||
|
return LeftFold(
|
||||||
|
std::forward<Tuple>(tuple),
|
||||||
|
std::forward<T>(init),
|
||||||
|
[]<typename TT, typename F>(TT&& value, F&& f) -> TT {
|
||||||
|
if(value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
return f();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <TupleLike Tuple>
|
template <TupleLike Tuple>
|
||||||
inline constexpr auto Filter(Tuple&& tuple, auto&& f) {
|
inline constexpr auto Filter(Tuple&& tuple, auto&& f) {
|
||||||
return [&]<auto... Is>(std::index_sequence<Is...>){
|
return LeftFold(
|
||||||
return TupleCat([&]<auto I>(Wrapper<I>){
|
std::forward<Tuple>(tuple),
|
||||||
constexpr bool flag = decltype(f(Get<I>(tuple)))::kValue;
|
MakeTuple<Tuple>(),
|
||||||
if constexpr(flag) {
|
[&]<TupleLike Accumulator, typename T>(Accumulator&& accumulator, T&& add) {
|
||||||
return MakeTuple<Tuple>(Get<I>(tuple));
|
if constexpr(decltype(f(std::forward<T>(add))){}) {
|
||||||
|
return TupleCat(std::forward<Accumulator>(accumulator), std::forward<T>(add));
|
||||||
} else {
|
} else {
|
||||||
return MakeTuple<Tuple>();
|
return accumulator;
|
||||||
};
|
};
|
||||||
}(Wrapper<Is>{})...);
|
}
|
||||||
}(std::make_index_sequence<kTupleSize<Tuple>>());
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
} // namespace utempl
|
||||||
|
|
Loading…
Reference in a new issue