diff options
Diffstat (limited to 'Rx/v2/src/rxcpp/operators/rx-switch_if_empty.hpp')
-rw-r--r-- | Rx/v2/src/rxcpp/operators/rx-switch_if_empty.hpp | 108 |
1 files changed, 91 insertions, 17 deletions
diff --git a/Rx/v2/src/rxcpp/operators/rx-switch_if_empty.hpp b/Rx/v2/src/rxcpp/operators/rx-switch_if_empty.hpp index cf51109..b9bab52 100644 --- a/Rx/v2/src/rxcpp/operators/rx-switch_if_empty.hpp +++ b/Rx/v2/src/rxcpp/operators/rx-switch_if_empty.hpp @@ -2,6 +2,21 @@ #pragma once +/*! \file rx-switch_if_empty.hpp + + \brief If the source Observable terminates without emitting any items, emits items from a backup Observable. + + \tparam BackupSource the type of the backup observable. + + \param t a backup observable that is used if the source observable is empty. + + \return Observable that emits items from a backup observable if the source observable is empty. + + \sample + \snippet switch_if_empty.cpp switch_if_empty sample + \snippet output.txt switch_if_empty sample +*/ + #if !defined(RXCPP_OPERATORS_RX_SWITCH_IF_EMPTY_HPP) #define RXCPP_OPERATORS_RX_SWITCH_IF_EMPTY_HPP @@ -13,6 +28,16 @@ namespace operators { namespace detail { +template<class... AN> +struct switch_if_empty_invalid_arguments {}; + +template<class... AN> +struct switch_if_empty_invalid : public rxo::operator_base<switch_if_empty_invalid_arguments<AN...>> { + using type = observable<switch_if_empty_invalid_arguments<AN...>, switch_if_empty_invalid<AN...>>; +}; +template<class... AN> +using switch_if_empty_invalid_t = typename switch_if_empty_invalid<AN...>::type; + template<class T, class BackupSource> struct switch_if_empty { @@ -75,30 +100,79 @@ struct switch_if_empty } }; -template<class BackupSource> -class switch_if_empty_factory -{ - typedef rxu::decay_t<BackupSource> backup_source_type; - backup_source_type backup; -public: - switch_if_empty_factory(backup_source_type b) : backup(std::move(b)) {} - template<class Observable> - auto operator()(Observable&& source) - -> decltype(source.template lift<rxu::value_type_t<rxu::decay_t<Observable>>>(switch_if_empty<rxu::value_type_t<rxu::decay_t<Observable>>, backup_source_type>(backup))) { - return source.template lift<rxu::value_type_t<rxu::decay_t<Observable>>>(switch_if_empty<rxu::value_type_t<rxu::decay_t<Observable>>, backup_source_type>(backup)); - } -}; +} +/*! @copydoc rx-switch_if_empty.hpp +*/ +template<class... AN> +auto switch_if_empty(AN&&... an) + -> operator_factory<switch_if_empty_tag, AN...> { + return operator_factory<switch_if_empty_tag, AN...>(std::make_tuple(std::forward<AN>(an)...)); } -template<class BackupSource> -auto switch_if_empty(BackupSource&& b) - -> detail::switch_if_empty_factory<BackupSource> { - return detail::switch_if_empty_factory<BackupSource>(std::forward<BackupSource>(b)); +/*! \brief If the source Observable terminates without emitting any items, emits a default item and completes. + + \tparam Value the type of the value to emit. + + \param v the default value to emit. + + \return Observable that emits the specified default item if the source observable is empty. + + \sample + \snippet default_if_empty.cpp default_if_empty sample + \snippet output.txt default_if_empty sample +*/ +template<class... AN> +auto default_if_empty(AN&&... an) + -> operator_factory<default_if_empty_tag, AN...> { + return operator_factory<default_if_empty_tag, AN...>(std::make_tuple(std::forward<AN>(an)...)); } } +template<> +struct member_overload<switch_if_empty_tag> +{ + template<class Observable, class BackupSource, + class Enabled = rxu::enable_if_all_true_type_t< + all_observables<Observable, BackupSource>>, + class SourceValue = rxu::value_type_t<Observable>, + class SwitchIfEmpty = rxo::detail::switch_if_empty<SourceValue, rxu::decay_t<BackupSource>>> + static auto member(Observable&& o, BackupSource&& b) + -> decltype(o.template lift<SourceValue>(SwitchIfEmpty(std::forward<BackupSource>(b)))) { + return o.template lift<SourceValue>(SwitchIfEmpty(std::forward<BackupSource>(b))); + } + + template<class... AN> + static operators::detail::switch_if_empty_invalid_t<AN...> member(AN...) { + std::terminate(); + return {}; + static_assert(sizeof...(AN) == 10000, "switch_if_empty takes (BackupSource)"); + } +}; + +template<> +struct member_overload<default_if_empty_tag> +{ + template<class Observable, class Value, + class Enabled = rxu::enable_if_all_true_type_t< + is_observable<Observable>>, + class SourceValue = rxu::value_type_t<Observable>, + class BackupSource = decltype(rxs::from(std::declval<SourceValue>())), + class DefaultIfEmpty = rxo::detail::switch_if_empty<SourceValue, BackupSource>> + static auto member(Observable&& o, Value v) + -> decltype(o.template lift<SourceValue>(DefaultIfEmpty(rxs::from(std::move(v))))) { + return o.template lift<SourceValue>(DefaultIfEmpty(rxs::from(std::move(v)))); + } + + template<class... AN> + static operators::detail::switch_if_empty_invalid_t<AN...> member(AN...) { + std::terminate(); + return {}; + static_assert(sizeof...(AN) == 10000, "default_if_empty takes (Value)"); + } +}; + } #endif |