mirror of
https://github.com/Naios/continuable.git
synced 2025-12-08 01:36:46 +08:00
Make use of C++17 if constexpr if available
* Supply a polyfill if it is not available
This commit is contained in:
parent
d30814c2ff
commit
14ebb40756
@ -52,15 +52,15 @@
|
||||
// Detect if the whole standard is available
|
||||
#if (defined(_MSC_VER) && defined(_HAS_CXX17) && _HAS_CXX17) || \
|
||||
(__cplusplus >= 201703L)
|
||||
#define CONTINUABLE_HAS_CXX17_CONSTEXPR_IF
|
||||
#define CONTINUABLE_HAS_CXX17_IF_CONSTEXPR
|
||||
#define CONTINUABLE_HAS_CXX17_DISJUNCTION
|
||||
#define CONTINUABLE_HAS_CXX17_CONJUNCTION
|
||||
#else
|
||||
// Generic feature detection based on __has_feature
|
||||
#if defined(__has_feature)
|
||||
#if !defined(CONTINUABLE_HAS_CXX17_CONSTEXPR_IF) && \
|
||||
#if !defined(CONTINUABLE_HAS_CXX17_IF_CONSTEXPR) && \
|
||||
__has_feature(cxx_if_constexpr)
|
||||
#define CONTINUABLE_HAS_CXX17_CONSTEXPR_IF
|
||||
#define CONTINUABLE_HAS_CXX17_IF_CONSTEXPR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -102,32 +102,78 @@ struct deduce_to_void : std::common_type<void> {};
|
||||
template <typename... T>
|
||||
using void_t = typename detail::deduce_to_void<T...>::type;
|
||||
|
||||
#if defined(CONTINUABLE_HAS_CXX17_IF_CONSTEXPR)
|
||||
#define CONTINUABLE_IF_CONSTEXPR_SELECT_2(EXPR, TRUE_BRANCH) \
|
||||
[&](auto) mutable { \
|
||||
if constexpr (EXPR) { \
|
||||
TRUE_BRANCH \
|
||||
} \
|
||||
}(0)
|
||||
#define CONTINUABLE_IF_CONSTEXPR_SELECT_3(EXPR, TRUE_BRANCH, FALSE_BRANCH) \
|
||||
[&](auto) mutable { \
|
||||
if constexpr (EXPR) { \
|
||||
TRUE_BRANCH \
|
||||
} else { \
|
||||
FALSE_BRANCH \
|
||||
} \
|
||||
}(0)
|
||||
#else
|
||||
namespace detail {
|
||||
template <typename Type, typename TrueCallback>
|
||||
constexpr void static_if_impl(std::true_type, Type&& type,
|
||||
TrueCallback&& trueCallback) {
|
||||
std::forward<TrueCallback>(trueCallback)(std::forward<Type>(type));
|
||||
template <typename TrueCallback>
|
||||
constexpr void static_if_impl(std::true_type, TrueCallback&& trueCallback) {
|
||||
std::forward<TrueCallback>(trueCallback)(0);
|
||||
}
|
||||
|
||||
template <typename Type, typename TrueCallback>
|
||||
constexpr void static_if_impl(std::false_type, Type&& /*type*/,
|
||||
template <typename TrueCallback>
|
||||
constexpr void static_if_impl(std::false_type,
|
||||
TrueCallback&& /*trueCallback*/) {
|
||||
}
|
||||
|
||||
template <typename Type, typename TrueCallback, typename FalseCallback>
|
||||
constexpr auto static_if_impl(std::true_type, Type&& type,
|
||||
TrueCallback&& trueCallback,
|
||||
template <typename TrueCallback, typename FalseCallback>
|
||||
constexpr auto static_if_impl(std::true_type, TrueCallback&& trueCallback,
|
||||
FalseCallback&& /*falseCallback*/) {
|
||||
return std::forward<TrueCallback>(trueCallback)(std::forward<Type>(type));
|
||||
return std::forward<TrueCallback>(trueCallback)(0);
|
||||
}
|
||||
|
||||
template <typename Type, typename TrueCallback, typename FalseCallback>
|
||||
constexpr auto static_if_impl(std::false_type, Type&& type,
|
||||
TrueCallback&& /*trueCallback*/,
|
||||
template <typename TrueCallback, typename FalseCallback>
|
||||
constexpr auto static_if_impl(std::false_type, TrueCallback&& /*trueCallback*/,
|
||||
FalseCallback&& falseCallback) {
|
||||
return std::forward<FalseCallback>(falseCallback)(std::forward<Type>(type));
|
||||
return std::forward<FalseCallback>(falseCallback)(0);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
#define CONTINUABLE_IF_CONSTEXPR_SELECT_2(EXPR, TRUE_BRANCH) \
|
||||
cti::detail::traits::detail::static_if_impl( \
|
||||
std::integral_constant<bool, EXPR>{}, [&](auto) mutable { TRUE_BRANCH })
|
||||
|
||||
#define CONTINUABLE_IF_CONSTEXPR_SELECT_3(EXPR, TRUE_BRANCH, FALSE_BRANCH) \
|
||||
cti::detail::traits::detail::static_if_impl( \
|
||||
std::integral_constant<bool, EXPR>{}, [&](auto) mutable { TRUE_BRANCH }, \
|
||||
[&](auto) { FALSE_BRANCH })
|
||||
#endif // CONTINUABLE_HAS_CXX17_IF_CONSTEXPR
|
||||
|
||||
// https://stackoverflow.com/questions/16374776/macro-overloading
|
||||
// compute number of (variadic) macro arguments from
|
||||
// http://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1
|
||||
#define CONTINUABLE_EXPAND(X) X // for MSVC10 compatibility
|
||||
#define CONTINUABLE_PP_NARG(...) \
|
||||
CONTINUABLE_EXPAND(CONTINUABLE_PP_NARG_(__VA_ARGS__, CONTINUABLE_PP_RSEQ_N()))
|
||||
#define CONTINUABLE_PP_NARG_(...) \
|
||||
CONTINUABLE_EXPAND(CONTINUABLE_PP_ARG_N(__VA_ARGS__))
|
||||
#define CONTINUABLE_PP_ARG_N(_1, _2, _3, N, ...) N
|
||||
#define CONTINUABLE_PP_RSEQ_N() 3, 2, 1, 0
|
||||
|
||||
#define CONTINUABLE_IF_CONSTEXPR_SELECT_(N) CONTINUABLE_IF_CONSTEXPR_SELECT_##N
|
||||
#define CONTINUABLE_IF_CONSTEXPR_SELECT_EVAL(N) \
|
||||
CONTINUABLE_IF_CONSTEXPR_SELECT_(N)
|
||||
|
||||
/// Polyfill for C++17 if constexpr, uses if constexpr when available,
|
||||
/// otherwise a polyfill through lambdas is used.
|
||||
#define CONTINUABLE_IF_CONSTEXPR(...) \
|
||||
CONTINUABLE_EXPAND(CONTINUABLE_IF_CONSTEXPR_SELECT_EVAL( \
|
||||
CONTINUABLE_EXPAND(CONTINUABLE_PP_NARG(__VA_ARGS__)))(__VA_ARGS__))
|
||||
|
||||
namespace detail {
|
||||
/// Evaluates to the size of the given tuple like type,
|
||||
// / if the type has no static size it will be one.
|
||||
template <typename T, typename Enable = void>
|
||||
@ -159,27 +205,6 @@ constexpr auto sequence_of(identity<T>) noexcept {
|
||||
return std::make_index_sequence<size>();
|
||||
}
|
||||
|
||||
/// Invokes the callback only if the given type matches the check
|
||||
template <typename Type, typename Check, typename TrueCallback>
|
||||
constexpr void static_if(Type&& type, Check&& check,
|
||||
TrueCallback&& trueCallback) {
|
||||
detail::static_if_impl(std::forward<Check>(check)(type),
|
||||
std::forward<Type>(type),
|
||||
std::forward<TrueCallback>(trueCallback));
|
||||
}
|
||||
|
||||
/// Invokes the callback only if the given type matches the check
|
||||
template <typename Type, typename Check, typename TrueCallback,
|
||||
typename FalseCallback>
|
||||
constexpr auto static_if(Type&& type, Check&& check,
|
||||
TrueCallback&& trueCallback,
|
||||
FalseCallback&& falseCallback) {
|
||||
return detail::static_if_impl(std::forward<Check>(check)(type),
|
||||
std::forward<Type>(type),
|
||||
std::forward<TrueCallback>(trueCallback),
|
||||
std::forward<FalseCallback>(falseCallback));
|
||||
}
|
||||
|
||||
/// Calls the given unpacker with the content of the given sequence
|
||||
template <typename U, std::size_t... I>
|
||||
constexpr decltype(auto) unpack(std::integer_sequence<std::size_t, I...>,
|
||||
|
||||
@ -266,10 +266,4 @@ private:
|
||||
} // 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
|
||||
|
||||
#endif // CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user