mirror of
https://github.com/Naios/continuable.git
synced 2025-12-07 01:06:44 +08:00
More constexpr conversions
This commit is contained in:
parent
933d773c4c
commit
fb4eb379ca
@ -333,7 +333,7 @@ auto make_all_result_submitter(Callback&& callback,
|
|||||||
/// A callable object to merge multiple signature hints together
|
/// A callable object to merge multiple signature hints together
|
||||||
struct entry_merger {
|
struct entry_merger {
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
constexpr auto operator()(T&... entries) noexcept {
|
constexpr auto operator()(T&... entries) const noexcept {
|
||||||
return traits::merge(hints::hint_of(traits::identity_of(entries))...);
|
return traits::merge(hints::hint_of(traits::identity_of(entries))...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -400,37 +400,53 @@ auto make_any_result_submitter(Callback&& callback) {
|
|||||||
std::forward<decltype(callback)>(callback));
|
std::forward<decltype(callback)>(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T>
|
||||||
constexpr T first_of(traits::identity<T, Args...>) noexcept;
|
struct check_pack_empty {
|
||||||
|
static constexpr auto const is_empty =
|
||||||
template <typename Signature, typename... Args>
|
(decltype(traits::pack_size_of(std::declval<T>())){} ==
|
||||||
constexpr auto common_result_of(Signature signature,
|
traits::size_constant_of<0>());
|
||||||
hints::signature_hint_tag<>, Args... /*args*/) {
|
|
||||||
/// Assert that the other signatures are empty too which means all signatures
|
|
||||||
/// had the same size.
|
|
||||||
traits::static_for_each_in(traits::identity<Args...>{}, [&](auto rest) {
|
|
||||||
auto is_empty =
|
|
||||||
(traits::pack_size_of(rest) == traits::size_constant_of<0>());
|
|
||||||
static_assert(is_empty.value, "Expected all continuations to have the same"
|
static_assert(is_empty.value, "Expected all continuations to have the same"
|
||||||
"count of arguments!");
|
"count of arguments!");
|
||||||
});
|
};
|
||||||
|
|
||||||
|
/// A callable object to determine the shared result between all continuations
|
||||||
|
struct determine_shared_result {
|
||||||
|
template <typename... T>
|
||||||
|
constexpr auto operator()(T&... args) const noexcept {
|
||||||
|
return common_result_of(hints::signature_hint_tag<>{},
|
||||||
|
hints::hint_of(traits::identity_of(args))...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <typename Signature, typename... Args>
|
||||||
|
static constexpr auto common_result_of(Signature signature,
|
||||||
|
hints::signature_hint_tag<>,
|
||||||
|
Args... /*args*/) {
|
||||||
|
/// Assert that the other signatures are empty too which means all
|
||||||
|
/// signatures had the same size.
|
||||||
|
std::initializer_list<int>{0, ((void)check_pack_empty<Args>{}, 0)...};
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... Args>
|
||||||
|
static constexpr T first_of(traits::identity<T, Args...>) noexcept;
|
||||||
|
|
||||||
/// Determine the common result between all continuation which are chained
|
/// Determine the common result between all continuation which are chained
|
||||||
/// with an `any` strategy, consider two continuations:
|
/// with an `any` strategy, consider two continuations:
|
||||||
/// c1 with `void(int)` and c2 with `void(float)`, the common result shared
|
/// c1 with `void(int)` and c2 with `void(float)`, the common result shared
|
||||||
/// between both continuations is `void(int)`.
|
/// between both continuations is `void(int)`.
|
||||||
template <typename Signature, typename First, typename... Args>
|
template <typename Signature, typename First, typename... Args>
|
||||||
constexpr auto common_result_of(Signature signature, First first,
|
static constexpr auto common_result_of(Signature signature, First first,
|
||||||
Args... args) {
|
Args... args) {
|
||||||
using Common =
|
using common_type =
|
||||||
traits::identity<std::common_type_t<decltype(first_of(first)),
|
traits::identity<std::common_type_t<decltype(first_of(first)),
|
||||||
decltype(first_of(args))...>>;
|
decltype(first_of(args))...>>;
|
||||||
|
|
||||||
return common_result_of(traits::push(signature, Common{}),
|
return common_result_of(traits::push(signature, common_type{}),
|
||||||
traits::pop_first(first), traits::pop_first(args)...);
|
traits::pop_first(first),
|
||||||
|
traits::pop_first(args)...);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/// Finalizes the any logic of a given composition
|
/// Finalizes the any logic of a given composition
|
||||||
template <typename Data>
|
template <typename Data>
|
||||||
@ -441,11 +457,8 @@ auto finalize_composition(
|
|||||||
|
|
||||||
auto composition = base::attorney::consume_data(std::move(continuation));
|
auto composition = base::attorney::consume_data(std::move(continuation));
|
||||||
|
|
||||||
// Determine the shared result between all continuations
|
constexpr auto signature =
|
||||||
auto signature = traits::unpack(composition, [](auto const&... args) {
|
traits::unpack(composition, determine_shared_result{});
|
||||||
return common_result_of(hints::signature_hint_tag<>{},
|
|
||||||
hints::hint_of(traits::identity_of(args))...);
|
|
||||||
});
|
|
||||||
|
|
||||||
return base::attorney::create(
|
return base::attorney::create(
|
||||||
[composition = std::move(composition)](auto&& callback) mutable {
|
[composition = std::move(composition)](auto&& callback) mutable {
|
||||||
|
|||||||
@ -203,6 +203,18 @@ constexpr auto static_if_impl(std::false_type, Type&& type,
|
|||||||
FalseCallback&& falseCallback) {
|
FalseCallback&& falseCallback) {
|
||||||
return std::forward<FalseCallback>(falseCallback)(std::forward<Type>(type));
|
return std::forward<FalseCallback>(falseCallback)(std::forward<Type>(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Applies the given callable to all objects in a sequence
|
||||||
|
template <typename C>
|
||||||
|
struct apply_to_all {
|
||||||
|
C callable;
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
constexpr void operator()(T&&... args) {
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
0, ((void)callable(std::forward<decltype(args)>(args)), 0)...};
|
||||||
|
}
|
||||||
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/// Returns the pack size of the given type
|
/// Returns the pack size of the given type
|
||||||
@ -340,22 +352,20 @@ constexpr auto unpack(F&& firstSequenceable, S&& secondSequenceable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Applies the handler function to each element contained in the sequenceable
|
/// Applies the handler function to each element contained in the sequenceable
|
||||||
|
// TODO Maybe crashes MSVC in constexpr mode
|
||||||
template <typename Sequenceable, typename Handler>
|
template <typename Sequenceable, typename Handler>
|
||||||
constexpr void static_for_each_in(Sequenceable&& sequenceable,
|
constexpr void static_for_each_in(Sequenceable&& sequenceable,
|
||||||
Handler&& handler) {
|
Handler&& handler) {
|
||||||
unpack(
|
unpack(std::forward<Sequenceable>(sequenceable),
|
||||||
std::forward<Sequenceable>(sequenceable), [&](auto&&... entries) mutable {
|
detail::apply_to_all<std::decay_t<Handler>>{
|
||||||
// Apply the consume function to every entry inside the pack
|
std::forward<Handler>(handler)});
|
||||||
(void)std::initializer_list<int>{
|
|
||||||
0, ((void)handler(std::forward<decltype(entries)>(entries)), 0)...};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the given type at the back of the left sequenceable
|
/// Adds the given type at the back of the left sequenceable
|
||||||
template <typename Left, typename Element>
|
template <typename Left, typename Element>
|
||||||
constexpr auto push(Left&& left, Element&& element) {
|
constexpr auto push(Left&& left, Element&& element) {
|
||||||
return unpack(std::forward<Left>(left), [&](auto&&... leftArgs) {
|
return unpack(std::forward<Left>(left), [&](auto&&... args) {
|
||||||
return std::make_tuple(std::forward<decltype(leftArgs)>(leftArgs)...,
|
return std::make_tuple(std::forward<decltype(args)>(args)...,
|
||||||
std::forward<Element>(element));
|
std::forward<Element>(element));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user