mirror of
https://github.com/Naios/continuable.git
synced 2026-01-01 03:12:12 +08:00
Allow basic emulation of C++17 fold expressions
This commit is contained in:
parent
04539ba638
commit
b67ca1c224
@ -677,8 +677,8 @@ template <typename... Continuables>
|
||||
auto when_all(Continuables&&... continuables) {
|
||||
static_assert(sizeof...(continuables) >= 2,
|
||||
"Requires at least 2 continuables!");
|
||||
return detail::traits::fold(detail::traits::and_folding(),
|
||||
std::forward<Continuables>(continuables)...);
|
||||
return CONTINUABLE_FOLD_EXPRESSION(
|
||||
&&, std::forward<Continuables>(continuables)...);
|
||||
}
|
||||
|
||||
/// Connects the given continuables with an *any* logic.
|
||||
@ -693,8 +693,8 @@ template <typename... Continuables>
|
||||
auto when_any(Continuables&&... continuables) {
|
||||
static_assert(sizeof...(continuables) >= 2,
|
||||
"Requires at least 2 continuables!");
|
||||
return detail::traits::fold(detail::traits::or_folding(),
|
||||
std::forward<Continuables>(continuables)...);
|
||||
return CONTINUABLE_FOLD_EXPRESSION(
|
||||
||, std::forward<Continuables>(continuables)...);
|
||||
}
|
||||
|
||||
/// Connects the given continuables with a *seq* logic.
|
||||
@ -709,8 +709,8 @@ template <typename... Continuables>
|
||||
auto when_seq(Continuables&&... continuables) {
|
||||
static_assert(sizeof...(continuables) >= 2,
|
||||
"Requires at least 2 continuables!");
|
||||
return detail::traits::fold(detail::traits::seq_folding(),
|
||||
std::forward<Continuables>(continuables)...);
|
||||
return CONTINUABLE_FOLD_EXPRESSION(
|
||||
>>, std::forward<Continuables>(continuables)...);
|
||||
}
|
||||
} // namespace cti
|
||||
|
||||
|
||||
@ -47,7 +47,9 @@
|
||||
#endif
|
||||
#endif // CONTINUABLE_WITH_NO_EXCEPTIONS
|
||||
|
||||
/// TODO Enable this
|
||||
#undef CONTINUABLE_HAS_CXX17_CONSTEXPR_IF
|
||||
/// TODO Enable this
|
||||
#undef CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED__
|
||||
|
||||
@ -401,41 +401,6 @@ constexpr auto merge(identity<LeftArgs...> /*left*/,
|
||||
std::forward<Rest>(rest)...);
|
||||
}
|
||||
|
||||
/// Combines the given arguments with the given folding function
|
||||
template <typename F, typename First>
|
||||
constexpr auto fold(F&& /*folder*/, First&& first) {
|
||||
return std::forward<First>(first);
|
||||
}
|
||||
/// Combines the given arguments with the given folding function
|
||||
template <typename F, typename First, typename Second, typename... Rest>
|
||||
auto fold(F&& folder, First&& first, Second&& second, Rest&&... rest) {
|
||||
auto res = folder(std::forward<First>(first), std::forward<Second>(second));
|
||||
return fold(std::forward<F>(folder), std::move(res),
|
||||
std::forward<Rest>(rest)...);
|
||||
}
|
||||
|
||||
/// Returns a folding function using operator `&&`.
|
||||
inline auto and_folding() noexcept {
|
||||
return [](auto&& left, auto&& right) {
|
||||
return std::forward<decltype(left)>(left) &&
|
||||
std::forward<decltype(right)>(right);
|
||||
};
|
||||
}
|
||||
/// Returns a folding function using operator `||`.
|
||||
inline auto or_folding() noexcept {
|
||||
return [](auto&& left, auto&& right) {
|
||||
return std::forward<decltype(left)>(left) ||
|
||||
std::forward<decltype(right)>(right);
|
||||
};
|
||||
}
|
||||
/// Returns a folding function using operator `>>`.
|
||||
inline auto seq_folding() noexcept {
|
||||
return [](auto&& left, auto&& right) {
|
||||
return std::forward<decltype(left)>(left) >>
|
||||
std::forward<decltype(right)>(right);
|
||||
};
|
||||
}
|
||||
|
||||
/// Deduces to a std::false_type
|
||||
template <typename T>
|
||||
using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
||||
@ -443,7 +408,4 @@ using fail = std::integral_constant<bool, !std::is_same<T, T>::value>;
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#define CONTINUABLE_CONSTEXPR_IF(EXPR, TRUE_BRANCH, FALSE_BRANCH)
|
||||
#define CONTINUABLE_FOLD_EXPRESSION(OPERATOR, SEQUENCE)
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED__
|
||||
|
||||
@ -260,8 +260,44 @@ private:
|
||||
*(volatile int*)0 = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Exposes functionality to emulate later standard features
|
||||
namespace emulation {
|
||||
#ifndef CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION
|
||||
/// Combines the given arguments with the given folding function
|
||||
template <typename F, typename First>
|
||||
constexpr auto fold(F&& /*folder*/, First&& first) {
|
||||
return std::forward<First>(first);
|
||||
}
|
||||
/// Combines the given arguments with the given folding function
|
||||
template <typename F, typename First, typename Second, typename... Rest>
|
||||
auto fold(F&& folder, First&& first, Second&& second, Rest&&... rest) {
|
||||
auto res = folder(std::forward<First>(first), std::forward<Second>(second));
|
||||
return fold(std::forward<F>(folder), std::move(res),
|
||||
std::forward<Rest>(rest)...);
|
||||
}
|
||||
#endif // CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION
|
||||
} // namespace emulation
|
||||
} // namespace util
|
||||
} // namespace detail
|
||||
} // namespace cti
|
||||
|
||||
#ifdef CONTINUABLE_CONSTEXPR_IF
|
||||
#define CONTINUABLE_CONSTEXPR_IF(EXPR, TRUE_BRANCH, FALSE_BRANCH)
|
||||
#else
|
||||
#define CONTINUABLE_CONSTEXPR_IF(EXPR, TRUE_BRANCH, FALSE_BRANCH)
|
||||
#endif // CONTINUABLE_CONSTEXPR_IF
|
||||
|
||||
#ifdef CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION
|
||||
#define CONTINUABLE_FOLD_EXPRESSION(OP, PACK) (... OP PACK)
|
||||
#else
|
||||
#define CONTINUABLE_FOLD_EXPRESSION(OP, PACK) \
|
||||
cti::detail::util::emulation::fold( \
|
||||
[](auto&& left, auto&& right) { \
|
||||
return std::forward<decltype(left)>(left) \
|
||||
OP std::forward<decltype(right)>(right); \
|
||||
}, \
|
||||
PACK);
|
||||
#endif // CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED__
|
||||
|
||||
@ -39,7 +39,7 @@ TEST(regression_tests, are_multiple_args_mergeable) {
|
||||
std::make_tuple(1, 2, 3, 4));
|
||||
|
||||
auto count = traits::unpack(tp2, [](auto... args) {
|
||||
return traits::fold(std::plus<int>{}, args...);
|
||||
return CONTINUABLE_FOLD_EXPRESSION(+, args...);
|
||||
});
|
||||
EXPECT_EQ(count, 20);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user