Fix kSeq, add default for f in LeftFold, add example for LeftFold
This commit is contained in:
parent
2be45e896a
commit
16889ef3b0
2 changed files with 29 additions and 27 deletions
|
@ -5,5 +5,7 @@ auto main() -> int {
|
||||||
utempl::GetIndexesTuple<4>(), utempl::kWrapper<std::size_t{}>, []<std::size_t I>(utempl::Wrapper<I>, auto) -> utempl::Wrapper<I + 1> {
|
utempl::GetIndexesTuple<4>(), utempl::kWrapper<std::size_t{}>, []<std::size_t I>(utempl::Wrapper<I>, auto) -> utempl::Wrapper<I + 1> {
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
static_assert(std::is_same_v<decltype(value), const utempl::Wrapper<static_cast<std::size_t>(4)>>);
|
static_assert(std::is_same_v<decltype(value), const utempl::Wrapper<static_cast<std::size_t>(4)>>);
|
||||||
|
static_assert(std::is_same_v<decltype(utempl::LeftFold(utempl::Tuple{}, value)), const utempl::Wrapper<static_cast<std::size_t>(4)>&>);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
namespace utempl {
|
namespace utempl {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using ForwardType = decltype(std::forward<T>(std::declval<T>()));
|
||||||
|
|
||||||
template <auto Value>
|
template <auto Value>
|
||||||
struct Wrapper {
|
struct Wrapper {
|
||||||
static constexpr auto kValue = Value;
|
static constexpr auto kValue = Value;
|
||||||
|
@ -26,13 +29,22 @@ struct Wrapper {
|
||||||
template <auto Value>
|
template <auto Value>
|
||||||
inline constexpr Wrapper<Value> kWrapper;
|
inline constexpr Wrapper<Value> kWrapper;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
requires std::same_as<T, void> || requires { T{}; }
|
||||||
|
constexpr auto kDefaultCreator = [] {
|
||||||
|
return T{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
constexpr auto kDefaultCreator<void> = [] {};
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
struct kSeq {
|
struct kSeq {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
friend constexpr auto operator|(F&& f, const kSeq<N>&) {
|
friend constexpr auto operator|(F&& f, const kSeq<N>&) -> decltype(auto) {
|
||||||
return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
|
return [&]<std::size_t... Is>(std::index_sequence<Is...>) -> decltype(auto) {
|
||||||
return std::forward<F>(f)(kWrapper<Is>...);
|
return std::forward<F>(f)(kWrapper<Is>...);
|
||||||
}(std::make_index_sequence<N>());
|
}(std::make_index_sequence<N>());
|
||||||
};
|
};
|
||||||
|
@ -430,9 +442,8 @@ struct LeftFold<T, F> {
|
||||||
T data;
|
T data;
|
||||||
F f;
|
F f;
|
||||||
template <typename TT>
|
template <typename TT>
|
||||||
constexpr auto operator|(LeftFold<TT>&& other) {
|
constexpr auto operator|(LeftFold<TT>&& other) -> LeftFold<std::invoke_result_t<F, T, TT>, F> {
|
||||||
using R = decltype(f(std::move(this->data), std::move(other.data)));
|
return {.data = std::forward<F>(this->f)(std::forward<T>(this->data), std::forward<TT>(other.data)), .f = std::forward<F>(this->f)};
|
||||||
return LeftFold<R, F>{.data = f(std::move(this->data), std::move(other.data)), .f = this->f};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -447,9 +458,7 @@ template <typename F, typename T>
|
||||||
struct LeftFoldIsOk {
|
struct LeftFoldIsOk {
|
||||||
static constexpr bool value = true;
|
static constexpr bool value = true;
|
||||||
template <typename TT>
|
template <typename TT>
|
||||||
consteval auto operator|(LeftFoldIsOk<F, TT>&& other) -> LeftFoldIsOk<F, std::invoke_result_t<F, T, TT>>
|
consteval auto operator|(LeftFoldIsOk<F, TT>&& other) -> LeftFoldIsOk<F, std::invoke_result_t<F, T, TT>> {
|
||||||
requires Function<F, void(T, TT)>
|
|
||||||
{
|
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
consteval auto operator|(auto&&) -> LeftFoldIgnorer {
|
consteval auto operator|(auto&&) -> LeftFoldIgnorer {
|
||||||
|
@ -464,23 +473,23 @@ concept LeftFoldConcept = decltype(Unpack(std::declval<Tuple>(), []<typename...
|
||||||
|
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
||||||
template <TupleLike Tuple, std::move_constructible T, impl::LeftFoldConcept<T, Tuple> F>
|
template <TupleLike Tuple, std::move_constructible T, impl::LeftFoldConcept<T, Tuple> F = decltype(kDefaultCreator<void>)&>
|
||||||
constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f) {
|
constexpr auto LeftFold(Tuple&& tuple, T&& init, F&& f = kDefaultCreator<void>) -> decltype(auto) {
|
||||||
return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) {
|
return Unpack(std::forward<Tuple>(tuple), [&]<typename... Ts>(Ts&&... args) -> decltype(auto) {
|
||||||
return (impl::LeftFold<std::remove_cvref_t<T>, F>{.data = std::forward<T>(init), .f = std::forward<F>(f)} | ... |
|
return (impl::LeftFold<ForwardType<T>, ForwardType<F>>{.data = std::forward<T>(init), .f = std::forward<F>(f)} | ... |
|
||||||
impl::LeftFold<std::remove_cvref_t<Ts>>{.data = std::forward<Ts>(args)})
|
impl::LeftFold<ForwardType<Ts>>{.data = std::forward<Ts>(args)})
|
||||||
.data;
|
.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
template <TupleLike Tuple, std::move_constructible T, impl::LeftFoldConcept<T, Tuple> F>
|
template <TupleLike Tuple, std::move_constructible T, impl::LeftFoldConcept<T, Tuple> F>
|
||||||
constexpr auto Reduce(Tuple&& tuple, T&& init, F&& f) {
|
constexpr auto Reduce(Tuple&& tuple, T&& init, F&& f) -> decltype(auto) {
|
||||||
return LeftFold(std::forward<Tuple>(tuple), std::forward<T>(init), std::forward<F>(f));
|
return LeftFold(std::forward<Tuple>(tuple), std::forward<T>(init), std::forward<F>(f));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
constexpr auto Reduce(T&& init, F&& f) {
|
constexpr auto Reduce(T&& init, F&& f) -> decltype(auto) {
|
||||||
return [init = std::forward<T>(init), f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple)
|
return [init = std::forward<T>(init), f = std::forward<F>(f)]<TupleLike Tuple>(Tuple&& tuple) -> decltype(auto)
|
||||||
requires impl::LeftFoldConcept<F, T, Tuple>
|
requires impl::LeftFoldConcept<F, T, Tuple>
|
||||||
{
|
{
|
||||||
return Reduce(std::forward<Tuple>(tuple), std::move(init), std::move(f));
|
return Reduce(std::forward<Tuple>(tuple), std::move(init), std::move(f));
|
||||||
|
@ -506,7 +515,7 @@ inline constexpr auto TupleCat(Tuples&&... tuples)
|
||||||
};
|
};
|
||||||
|
|
||||||
template <TupleLike... Tuples, typename F>
|
template <TupleLike... Tuples, typename F>
|
||||||
inline constexpr auto Unpack(Tuples&&... tuples, F&& f) {
|
inline constexpr auto Unpack(Tuples&&... tuples, F&& f) -> decltype(Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f))) {
|
||||||
return Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f));
|
return Unpack(TupleCat(std::forward<Tuples>(tuples)...), std::forward<F>(f));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -680,15 +689,6 @@ constexpr auto Enumerate(Tuple&& tuple) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
requires std::same_as<T, void> || requires { T{}; }
|
|
||||||
constexpr auto kDefaultCreator = [] {
|
|
||||||
return T{};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
constexpr auto kDefaultCreator<void> = [] {};
|
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
template <typename Key, typename KeysTuple>
|
template <typename Key, typename KeysTuple>
|
||||||
|
|
Loading…
Reference in a new issue