Allow basic emulation of C++17 fold expressions

This commit is contained in:
Denis Blank 2017-10-04 04:28:42 +02:00
parent 04539ba638
commit b67ca1c224
5 changed files with 45 additions and 45 deletions

View File

@ -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

View File

@ -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__

View File

@ -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__

View File

@ -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__

View File

@ -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);
}