mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56: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
|
||||
struct entry_merger {
|
||||
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))...);
|
||||
}
|
||||
};
|
||||
@ -400,37 +400,53 @@ auto make_any_result_submitter(Callback&& callback) {
|
||||
std::forward<decltype(callback)>(callback));
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
constexpr T first_of(traits::identity<T, Args...>) noexcept;
|
||||
template <typename T>
|
||||
struct check_pack_empty {
|
||||
static constexpr auto const is_empty =
|
||||
(decltype(traits::pack_size_of(std::declval<T>())){} ==
|
||||
traits::size_constant_of<0>());
|
||||
static_assert(is_empty.value, "Expected all continuations to have the same"
|
||||
"count of arguments!");
|
||||
};
|
||||
|
||||
template <typename Signature, typename... Args>
|
||||
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.
|
||||
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"
|
||||
"count of arguments!");
|
||||
});
|
||||
return signature;
|
||||
}
|
||||
/// 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))...);
|
||||
}
|
||||
|
||||
/// Determine the common result between all continuation which are chained
|
||||
/// with an `any` strategy, consider two continuations:
|
||||
/// c1 with `void(int)` and c2 with `void(float)`, the common result shared
|
||||
/// between both continuations is `void(int)`.
|
||||
template <typename Signature, typename First, typename... Args>
|
||||
constexpr auto common_result_of(Signature signature, First first,
|
||||
Args... args) {
|
||||
using Common =
|
||||
traits::identity<std::common_type_t<decltype(first_of(first)),
|
||||
decltype(first_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 common_result_of(traits::push(signature, Common{}),
|
||||
traits::pop_first(first), traits::pop_first(args)...);
|
||||
}
|
||||
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
|
||||
/// with an `any` strategy, consider two continuations:
|
||||
/// c1 with `void(int)` and c2 with `void(float)`, the common result shared
|
||||
/// between both continuations is `void(int)`.
|
||||
template <typename Signature, typename First, typename... Args>
|
||||
static constexpr auto common_result_of(Signature signature, First first,
|
||||
Args... args) {
|
||||
using common_type =
|
||||
traits::identity<std::common_type_t<decltype(first_of(first)),
|
||||
decltype(first_of(args))...>>;
|
||||
|
||||
return common_result_of(traits::push(signature, common_type{}),
|
||||
traits::pop_first(first),
|
||||
traits::pop_first(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/// Finalizes the any logic of a given composition
|
||||
template <typename Data>
|
||||
@ -441,11 +457,8 @@ auto finalize_composition(
|
||||
|
||||
auto composition = base::attorney::consume_data(std::move(continuation));
|
||||
|
||||
// Determine the shared result between all continuations
|
||||
auto signature = traits::unpack(composition, [](auto const&... args) {
|
||||
return common_result_of(hints::signature_hint_tag<>{},
|
||||
hints::hint_of(traits::identity_of(args))...);
|
||||
});
|
||||
constexpr auto signature =
|
||||
traits::unpack(composition, determine_shared_result{});
|
||||
|
||||
return base::attorney::create(
|
||||
[composition = std::move(composition)](auto&& callback) mutable {
|
||||
|
||||
@ -203,6 +203,18 @@ constexpr auto static_if_impl(std::false_type, Type&& type,
|
||||
FalseCallback&& falseCallback) {
|
||||
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
|
||||
|
||||
/// 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
|
||||
// TODO Maybe crashes MSVC in constexpr mode
|
||||
template <typename Sequenceable, typename Handler>
|
||||
constexpr void static_for_each_in(Sequenceable&& sequenceable,
|
||||
Handler&& handler) {
|
||||
unpack(
|
||||
std::forward<Sequenceable>(sequenceable), [&](auto&&... entries) mutable {
|
||||
// Apply the consume function to every entry inside the pack
|
||||
(void)std::initializer_list<int>{
|
||||
0, ((void)handler(std::forward<decltype(entries)>(entries)), 0)...};
|
||||
});
|
||||
unpack(std::forward<Sequenceable>(sequenceable),
|
||||
detail::apply_to_all<std::decay_t<Handler>>{
|
||||
std::forward<Handler>(handler)});
|
||||
}
|
||||
|
||||
/// Adds the given type at the back of the left sequenceable
|
||||
template <typename Left, typename Element>
|
||||
constexpr auto push(Left&& left, Element&& element) {
|
||||
return unpack(std::forward<Left>(left), [&](auto&&... leftArgs) {
|
||||
return std::make_tuple(std::forward<decltype(leftArgs)>(leftArgs)...,
|
||||
return unpack(std::forward<Left>(left), [&](auto&&... args) {
|
||||
return std::make_tuple(std::forward<decltype(args)>(args)...,
|
||||
std::forward<Element>(element));
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user