• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //
trace_activity()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>
operator ()rxcpp::identity_observable294     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 {
operator ()rxcpp::identity_for304     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