Home | History | Annotate | Download | only in rxcpp
      1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
      2 
      3 #pragma once
      4 
      5 #if !defined(RXCPP_RX_PREDEF_HPP)
      6 #define RXCPP_RX_PREDEF_HPP
      7 
      8 #include "rx-includes.hpp"
      9 
     10 namespace rxcpp {
     11 
     12 //
     13 // create a typedef for rxcpp_trace_type to override the default
     14 //
     15 inline auto trace_activity() -> decltype(rxcpp_trace_activity(trace_tag()))& {
     16     static decltype(rxcpp_trace_activity(trace_tag())) trace;
     17     return trace;
     18 }
     19 
     20 
     21 struct tag_action {};
     22 template<class T, class C = rxu::types_checked>
     23 struct is_action : public std::false_type {};
     24 
     25 template<class T>
     26 struct is_action<T, typename rxu::types_checked_from<typename T::action_tag>::type>
     27     : public std::is_convertible<typename T::action_tag*, tag_action*> {};
     28 
     29 
     30 struct tag_worker {};
     31 template<class T>
     32 class is_worker
     33 {
     34     struct not_void {};
     35     template<class C>
     36     static typename C::worker_tag* check(int);
     37     template<class C>
     38     static not_void check(...);
     39 public:
     40     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_worker*>::value;
     41 };
     42 
     43 struct tag_scheduler {};
     44 template<class T>
     45 class is_scheduler
     46 {
     47     struct not_void {};
     48     template<class C>
     49     static typename C::scheduler_tag* check(int);
     50     template<class C>
     51     static not_void check(...);
     52 public:
     53     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_scheduler*>::value;
     54 };
     55 
     56 struct tag_schedulable {};
     57 template<class T>
     58 class is_schedulable
     59 {
     60     struct not_void {};
     61     template<class C>
     62     static typename C::schedulable_tag* check(int);
     63     template<class C>
     64     static not_void check(...);
     65 public:
     66     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_schedulable*>::value;
     67 };
     68 
     69 namespace detail
     70 {
     71 
     72 struct stateless_observer_tag {};
     73 
     74 }
     75 
     76 // state with optional overrides
     77 template<class T, class State = void, class OnNext = void, class OnError = void, class OnCompleted = void>
     78 class observer;
     79 
     80 // no state with optional overrides
     81 template<class T, class OnNext, class OnError, class OnCompleted>
     82 class observer<T, detail::stateless_observer_tag, OnNext, OnError, OnCompleted>;
     83 
     84 // virtual functions forward to dynamically allocated shared observer instance.
     85 template<class T>
     86 class observer<T, void, void, void, void>;
     87 
     88 struct tag_observer {};
     89 template<class T>
     90 class is_observer
     91 {
     92     template<class C>
     93     static typename C::observer_tag* check(int);
     94     template<class C>
     95     static void check(...);
     96 public:
     97     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_observer*>::value;
     98 };
     99 
    100 struct tag_dynamic_observer {};
    101 template<class T>
    102 class is_dynamic_observer
    103 {
    104     struct not_void {};
    105     template<class C>
    106     static typename C::dynamic_observer_tag* check(int);
    107     template<class C>
    108     static not_void check(...);
    109 public:
    110     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_dynamic_observer*>::value;
    111 };
    112 
    113 struct tag_subscriber {};
    114 template<class T>
    115 class is_subscriber
    116 {
    117     struct not_void {};
    118     template<class C>
    119     static typename C::subscriber_tag* check(int);
    120     template<class C>
    121     static not_void check(...);
    122 public:
    123     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_subscriber*>::value;
    124 };
    125 
    126 struct tag_dynamic_observable {};
    127 template<class T>
    128 class is_dynamic_observable
    129 {
    130     struct not_void {};
    131     template<class C>
    132     static typename C::dynamic_observable_tag* check(int);
    133     template<class C>
    134     static not_void check(...);
    135 public:
    136     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_dynamic_observable*>::value;
    137 };
    138 
    139 template<class T>
    140 class dynamic_observable;
    141 
    142 template<
    143     class T = void,
    144     class SourceObservable = typename std::conditional<std::is_same<T, void>::value,
    145         void, dynamic_observable<T>>::type>
    146 class observable;
    147 
    148 template<class T, class Source>
    149 observable<T> make_observable_dynamic(Source&&);
    150 
    151 template<class Selector, class Default, template<class... TN> class SO, class... AN>
    152 struct defer_observable;
    153 
    154 struct tag_observable {};
    155 template<class T>
    156 struct observable_base {
    157     typedef tag_observable observable_tag;
    158     typedef T value_type;
    159 };
    160 
    161 namespace detail {
    162 
    163 template<class T, class =rxu::types_checked>
    164 struct is_observable : std::false_type
    165 {
    166 };
    167 
    168 template<class T>
    169 struct is_observable<T, rxu::types_checked_t<typename T::observable_tag>>
    170     : std::is_convertible<typename T::observable_tag*, tag_observable*>
    171 {
    172 };
    173 
    174 }
    175 
    176 template<class T, class Decayed = rxu::decay_t<T>>
    177 struct is_observable : detail::is_observable<Decayed>
    178 {
    179 };
    180 
    181 template<class Observable, class DecayedObservable = rxu::decay_t<Observable>>
    182 using observable_tag_t = typename DecayedObservable::observable_tag;
    183 
    184 // extra indirection for vs2013 support
    185 template<class Types, class =rxu::types_checked>
    186 struct expand_observable_tags { struct type; };
    187 template<class... ObservableN>
    188 struct expand_observable_tags<rxu::types<ObservableN...>, rxu::types_checked_t<typename ObservableN::observable_tag...>>
    189 {
    190     using type = rxu::types<typename ObservableN::observable_tag...>;
    191 };
    192 template<class... ObservableN>
    193 using observable_tags_t = typename expand_observable_tags<rxu::types<ObservableN...>>::type;
    194 
    195 template<class... ObservableN>
    196 using all_observables = rxu::all_true_type<is_observable<ObservableN>...>;
    197 
    198 struct tag_dynamic_connectable_observable : public tag_dynamic_observable {};
    199 
    200 template<class T>
    201 class is_dynamic_connectable_observable
    202 {
    203     struct not_void {};
    204     template<class C>
    205     static typename C::dynamic_observable_tag* check(int);
    206     template<class C>
    207     static not_void check(...);
    208 public:
    209     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_dynamic_connectable_observable*>::value;
    210 };
    211 
    212 template<class T>
    213 class dynamic_connectable_observable;
    214 
    215 template<class T,
    216     class SourceObservable = typename std::conditional<std::is_same<T, void>::value,
    217         void, dynamic_connectable_observable<T>>::type>
    218 class connectable_observable;
    219 
    220 struct tag_connectable_observable : public tag_observable {};
    221 template<class T>
    222 class is_connectable_observable
    223 {
    224     template<class C>
    225     static typename C::observable_tag check(int);
    226     template<class C>
    227     static void check(...);
    228 public:
    229     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_connectable_observable>::value;
    230 };
    231 
    232 struct tag_dynamic_grouped_observable : public tag_dynamic_observable {};
    233 
    234 template<class T>
    235 class is_dynamic_grouped_observable
    236 {
    237     struct not_void {};
    238     template<class C>
    239     static typename C::dynamic_observable_tag* check(int);
    240     template<class C>
    241     static not_void check(...);
    242 public:
    243     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_dynamic_grouped_observable*>::value;
    244 };
    245 
    246 template<class K, class T>
    247 class dynamic_grouped_observable;
    248 
    249 template<class K, class T,
    250     class SourceObservable = typename std::conditional<std::is_same<T, void>::value,
    251         void, dynamic_grouped_observable<K, T>>::type>
    252 class grouped_observable;
    253 
    254 template<class K, class T, class Source>
    255 grouped_observable<K, T> make_dynamic_grouped_observable(Source&& s);
    256 
    257 struct tag_grouped_observable : public tag_observable {};
    258 template<class T>
    259 class is_grouped_observable
    260 {
    261     template<class C>
    262     static typename C::observable_tag check(int);
    263     template<class C>
    264     static void check(...);
    265 public:
    266     static const bool value = std::is_convertible<decltype(check<rxu::decay_t<T>>(0)), tag_grouped_observable>::value;
    267 };
    268 
    269 template<class Source, class Function>
    270 struct is_operator_factory_for {
    271     using function_type = rxu::decay_t<Function>;
    272     using source_type = rxu::decay_t<Source>;
    273 
    274 // check methods instead of void_t for vs2013 support
    275 
    276     struct tag_not_valid;
    277     template<class CS, class CO>
    278     static auto check(int) -> decltype((*(CS*)nullptr)((*(CO*)nullptr)));
    279     template<class CS, class CO>
    280     static tag_not_valid check(...);
    281 
    282     using type = decltype(check<function_type, source_type>(0));
    283 
    284     static const bool value = !std::is_same<type, tag_not_valid>::value && is_observable<source_type>::value;
    285 };
    286 
    287 //
    288 // this type is the default used by operators that subscribe to
    289 // multiple sources. It assumes that the sources are already synchronized
    290 //
    291 struct identity_observable
    292 {
    293     template<class Observable>
    294     auto operator()(Observable o)
    295         -> Observable {
    296         return      std::move(o);
    297         static_assert(is_observable<Observable>::value, "only support observables");
    298     }
    299 };
    300 
    301 template<class T>
    302 struct identity_for
    303 {
    304     T operator()(T t) {
    305         return      std::move(t);
    306     }
    307 };
    308 
    309 template<class T, class Seed, class Accumulator>
    310 struct is_accumulate_function_for {
    311 
    312     typedef rxu::decay_t<Accumulator> accumulator_type;
    313     typedef rxu::decay_t<Seed> seed_type;
    314     typedef T source_value_type;
    315 
    316     struct tag_not_valid {};
    317     template<class CS, class CV, class CRS>
    318     static auto check(int) -> decltype((*(CRS*)nullptr)(*(CS*)nullptr, *(CV*)nullptr));
    319     template<class CS, class CV, class CRS>
    320     static tag_not_valid check(...);
    321 
    322     typedef decltype(check<seed_type, source_value_type, accumulator_type>(0)) type;
    323     static const bool value = std::is_same<type, seed_type>::value;
    324 };
    325 
    326 }
    327 
    328 #endif
    329