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) { auto when_all(Continuables&&... continuables) {
static_assert(sizeof...(continuables) >= 2, static_assert(sizeof...(continuables) >= 2,
"Requires at least 2 continuables!"); "Requires at least 2 continuables!");
return detail::traits::fold(detail::traits::and_folding(), return CONTINUABLE_FOLD_EXPRESSION(
std::forward<Continuables>(continuables)...); &&, std::forward<Continuables>(continuables)...);
} }
/// Connects the given continuables with an *any* logic. /// Connects the given continuables with an *any* logic.
@ -693,8 +693,8 @@ template <typename... Continuables>
auto when_any(Continuables&&... continuables) { auto when_any(Continuables&&... continuables) {
static_assert(sizeof...(continuables) >= 2, static_assert(sizeof...(continuables) >= 2,
"Requires at least 2 continuables!"); "Requires at least 2 continuables!");
return detail::traits::fold(detail::traits::or_folding(), return CONTINUABLE_FOLD_EXPRESSION(
std::forward<Continuables>(continuables)...); ||, std::forward<Continuables>(continuables)...);
} }
/// Connects the given continuables with a *seq* logic. /// Connects the given continuables with a *seq* logic.
@ -709,8 +709,8 @@ template <typename... Continuables>
auto when_seq(Continuables&&... continuables) { auto when_seq(Continuables&&... continuables) {
static_assert(sizeof...(continuables) >= 2, static_assert(sizeof...(continuables) >= 2,
"Requires at least 2 continuables!"); "Requires at least 2 continuables!");
return detail::traits::fold(detail::traits::seq_folding(), return CONTINUABLE_FOLD_EXPRESSION(
std::forward<Continuables>(continuables)...); >>, std::forward<Continuables>(continuables)...);
} }
} // namespace cti } // namespace cti

View File

@ -47,7 +47,9 @@
#endif #endif
#endif // CONTINUABLE_WITH_NO_EXCEPTIONS #endif // CONTINUABLE_WITH_NO_EXCEPTIONS
/// TODO Enable this
#undef CONTINUABLE_HAS_CXX17_CONSTEXPR_IF #undef CONTINUABLE_HAS_CXX17_CONSTEXPR_IF
/// TODO Enable this
#undef CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION #undef CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION
#endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED__ #endif // CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED__

View File

@ -401,41 +401,6 @@ constexpr auto merge(identity<LeftArgs...> /*left*/,
std::forward<Rest>(rest)...); 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 /// Deduces to a std::false_type
template <typename T> template <typename T>
using fail = std::integral_constant<bool, !std::is_same<T, T>::value>; 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 detail
} // namespace cti } // namespace cti
#define CONTINUABLE_CONSTEXPR_IF(EXPR, TRUE_BRANCH, FALSE_BRANCH)
#define CONTINUABLE_FOLD_EXPRESSION(OPERATOR, SEQUENCE)
#endif // CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED__ #endif // CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED__

View File

@ -260,8 +260,44 @@ private:
*(volatile int*)0 = 0; *(volatile int*)0 = 0;
#endif #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 util
} // namespace detail } // namespace detail
} // namespace cti } // 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__ #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)); std::make_tuple(1, 2, 3, 4));
auto count = traits::unpack(tp2, [](auto... args) { auto count = traits::unpack(tp2, [](auto... args) {
return traits::fold(std::plus<int>{}, args...); return CONTINUABLE_FOLD_EXPRESSION(+, args...);
}); });
EXPECT_EQ(count, 20); EXPECT_EQ(count, 20);
} }