From 2508fab7d7ed4a0cdd7ad570e5ca5a5829aa0d05 Mon Sep 17 00:00:00 2001 From: Steven WdV <> Date: Tue, 16 Jan 2024 13:31:52 +0100 Subject: [PATCH] Fix C++20 compatibility Closes ReactiveX#602 --- Rx/v2/src/rxcpp/rx-util.hpp | 150 +++++++++++++++++------------------- 1 file changed, 72 insertions(+), 78 deletions(-) diff --git a/Rx/v2/src/rxcpp/rx-util.hpp b/Rx/v2/src/rxcpp/rx-util.hpp index d76fa76a1..c98953c87 100644 --- a/Rx/v2/src/rxcpp/rx-util.hpp +++ b/Rx/v2/src/rxcpp/rx-util.hpp @@ -28,6 +28,8 @@ #define RXCPP_MAKE_IDENTIFIER(Prefix) RXCPP_CONCAT_EVALUATE(Prefix, __LINE__) +#define RXCPP_DECLVAL(...) static_cast<__VA_ARGS__ (*)() noexcept>(nullptr)() + // Provide replacements for try/catch keywords, using which is a compilation error // when exceptions are disabled with -fno-exceptions. #if RXCPP_USE_EXCEPTIONS @@ -46,18 +48,13 @@ namespace util { template using value_type_t = typename std::decay::type::value_type; template using decay_t = typename std::decay::type; -#ifdef __cpp_lib_is_invocable -template struct result_of; -template -struct result_of -{ - using type = std::invoke_result_t; +template +struct callable_result { + using type = decltype(RXCPP_DECLVAL(Fn&&)(RXCPP_DECLVAL(ArgTypes&&)...)); }; -#else -template using result_of = std::result_of; -#endif -template using result_of_t = typename result_of::type; +template +using callable_result_t = typename callable_result::type; template std::vector to_vector(const T (&arr) [size]) { @@ -70,7 +67,7 @@ std::vector to_vector(std::initializer_list il) { } template -typename std::enable_if::value && std::is_pod::value, std::vector>::type to_vector(T0 t0, TN... tn) { +typename std::enable_if::value && std::is_trivial::value && std::is_standard_layout::value, std::vector>::type to_vector(T0 t0, TN... tn) { return to_vector({t0, tn...}); } @@ -93,13 +90,13 @@ struct values_from; template struct values_from { - typedef values type; + using type = values; }; template struct values_from { - typedef typename values_from::type type; + using type = typename values_from::type; }; template @@ -138,30 +135,30 @@ using enable_if_all_true_type_t = typename std::enable_if:: struct all_values_true { template - bool operator()(ValueN... vn) const; + bool operator()(const ValueN&... vn) const; template - bool operator()(Value0 v0) const { + bool operator()(const Value0& v0) const { return v0; } template - bool operator()(Value0 v0, ValueN... vn) const { + bool operator()(const Value0& v0, const ValueN&... vn) const { return v0 && all_values_true()(vn...); } }; struct any_value_true { template - bool operator()(ValueN... vn) const; + bool operator()(const ValueN&... vn) const; template - bool operator()(Value0 v0) const { + bool operator()(const Value0& v0) const { return v0; } template - bool operator()(Value0 v0, ValueN... vn) const { + bool operator()(const Value0& v0, const ValueN&... vn) const { return v0 || any_value_true()(vn...); } }; @@ -177,11 +174,11 @@ struct types {}; struct types_checked {}; namespace detail { -template struct types_checked_from {typedef types_checked type;}; +template struct types_checked_from { using type = types_checked; }; } template -struct types_checked_from {typedef typename detail::types_checked_from::type type;}; +struct types_checked_from { using type = typename detail::types_checked_from::type; }; template using types_checked_t = typename types_checked_from::type; @@ -199,17 +196,17 @@ using value_types_t = typename expand_value_types>::type; template -struct value_type_from : public std::false_type {typedef types_checked type;}; +struct value_type_from : public std::false_type { using type = types_checked; }; template struct value_type_from>::type> - : public std::true_type {typedef value_type_t type;}; + : public std::true_type { using type = value_type_t; }; namespace detail { -template -auto apply(std::tuple p, values, F&& f) - -> decltype(f(std::forward(std::get(p))...)) { - return f(std::forward(std::get(p))...); +template +auto apply(Tuple&& p, values, F&& f) + -> decltype(f(std::get(std::forward(p))...)) { + return f(std::get(std::forward(p))...); } template @@ -226,11 +223,17 @@ auto apply_to_each(std::tuple& p, values, const F_inn } template -auto apply(std::tuple p, F&& f) +auto apply(std::tuple&& p, F&& f) -> decltype(detail::apply(std::move(p), typename values_from::type(), std::forward(f))) { return detail::apply(std::move(p), typename values_from::type(), std::forward(f)); } +template +auto apply(const std::tuple& p, F&& f) + -> decltype(detail::apply(p, typename values_from::type(), std::forward(f))) { + return detail::apply(p, typename values_from::type(), std::forward(f)); +} + template auto apply_to_each(std::tuple& p, F_inner& f_inner, F_outer& f_outer) -> decltype(detail::apply_to_each(p, typename values_from::type(), f_inner, f_outer)) { @@ -304,14 +307,9 @@ template struct take_at { template - auto operator()(ParamN... pn) - -> typename std::tuple_element...>>::type { - return std::get(std::make_tuple(std::move(pn)...)); - } - template - auto operator()(ParamN... pn) const + auto operator()(const ParamN&... pn) const -> typename std::tuple_element...>>::type { - return std::get(std::make_tuple(std::move(pn)...)); + return std::get(std::tie(pn...)); } }; @@ -332,13 +330,13 @@ struct defer_trait template struct tag_valid {static const bool valid = true; static const bool value = R;}; struct tag_not_valid {static const bool valid = false; static const bool value = false;}; - typedef Deferred::type...> resolved_type; + using resolved_type = Deferred::type...>; template static auto check(int) -> tag_valid; template static tag_not_valid check(...); - typedef decltype(check(0)) tag_type; + using tag_type = decltype(check(0)); static const bool valid = tag_type::valid; static const bool value = tag_type::value; static const bool not_value = valid && !value; @@ -348,16 +346,16 @@ template class Deferred, class... AN> struct defer_type { template - struct tag_valid {typedef R type; static const bool value = true;}; - struct tag_not_valid {typedef void type; static const bool value = false;}; - typedef Deferred::type...> resolved_type; + struct tag_valid { using type = R; static const bool value = true;}; + struct tag_not_valid { using type = void; static const bool value = false;}; + using resolved_type = Deferred::type...>; template static auto check(int) -> tag_valid; template static tag_not_valid check(...); - typedef decltype(check(0)) tag_type; - typedef typename tag_type::type type; + using tag_type = decltype(check(0)); + using type = typename tag_type::type; static const bool value = tag_type::value; }; @@ -365,16 +363,16 @@ template class Deferred, class... AN> struct defer_value_type { template - struct tag_valid {typedef R type; static const bool value = true;}; - struct tag_not_valid {typedef void type; static const bool value = false;}; - typedef Deferred::type...> resolved_type; + struct tag_valid { using type = R; static const bool value = true;}; + struct tag_not_valid { using type = void; static const bool value = false;}; + using resolved_type = Deferred::type...>; template static auto check(int) -> tag_valid>; template static tag_not_valid check(...); - typedef decltype(check(0)) tag_type; - typedef typename tag_type::type type; + using tag_type = decltype(check(0)); + using type = typename tag_type::type; static const bool value = tag_type::value; }; @@ -382,38 +380,38 @@ template class Deferred, class... AN> struct defer_seed_type { template - struct tag_valid {typedef R type; static const bool value = true;}; - struct tag_not_valid {typedef void type; static const bool value = false;}; - typedef Deferred::type...> resolved_type; + struct tag_valid { using type = R; static const bool value = true;}; + struct tag_not_valid { using type = void; static const bool value = false;}; + using resolved_type = Deferred::type...>; template static auto check(int) -> tag_valid; template static tag_not_valid check(...); - typedef decltype(check(0)) tag_type; - typedef typename tag_type::type type; + using tag_type = decltype(check(0)); + using type = typename tag_type::type; static const bool value = tag_type::value; }; template struct resolve_type { - typedef D type; + using type = D; }; template class Deferred, class... AN> struct resolve_type> { - typedef typename defer_type::type type; + using type = typename defer_type::type; }; template class Deferred, class... AN> struct resolve_type> { - typedef typename defer_value_type::type type; + using type = typename defer_value_type::type; }; template class Deferred, class... AN> struct resolve_type> { - typedef typename defer_seed_type::type type; + using type = typename defer_seed_type::type; }; struct plus @@ -579,13 +577,20 @@ class maybe { } - maybe(T value) + maybe(const T& value) : is_set(false) { new (reinterpret_cast(&storage)) T(value); is_set = true; } + maybe(T&& value) + : is_set(false) + { + new (reinterpret_cast(&storage)) T(std::move(value)); + is_set = true; + } + maybe(const maybe& other) : is_set(false) { @@ -609,9 +614,9 @@ class maybe reset(); } - typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; + using value_type = T; + using iterator = T *; + using const_iterator = const T *; bool empty() const { return !is_set; @@ -699,12 +704,7 @@ namespace detail { struct surely { template - auto operator()(T... t) - -> decltype(std::make_tuple(t.get()...)) { - return std::make_tuple(t.get()...); - } - template - auto operator()(T... t) const + auto operator()(const T&... t) const -> decltype(std::make_tuple(t.get()...)) { return std::make_tuple(t.get()...); } @@ -831,7 +831,7 @@ struct is_duration : detail::is_duration {}; // C++17 negation namespace detail { template - struct not_value : std::conditional::type { + struct not_value : std::conditional_t { }; } @@ -996,22 +996,16 @@ struct filtered_hash::value>::type> }; template struct filtered_hash>::value>::type> { - using argument_type = T; - using result_type = std::size_t; - - result_type operator()(argument_type const & dur) const + std::size_t operator()(T const & dur) const { - return std::hash{}(dur.count()); + return std::hash{}(dur.count()); } }; template struct filtered_hash>::value>::type> { - using argument_type = T; - using result_type = std::size_t; - - result_type operator()(argument_type const & tp) const + std::size_t operator()(T const & tp) const { - return std::hash{}(tp.time_since_epoch().count()); + return std::hash{}(tp.time_since_epoch().count()); } }; @@ -1024,7 +1018,7 @@ struct is_hashable::result_type, typename filtered_hash::argument_type, - typename rxu::result_of(T)>::type>::type> + typename rxu::callable_result, T>::type>::type> : std::true_type {}; }