RxCpp
The Reactive Extensions for Native (RxCpp) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators in both C and C++.
rx-util.hpp
Go to the documentation of this file.
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_UTIL_HPP)
6 #define RXCPP_RX_UTIL_HPP
7 
8 #include "rx-includes.hpp"
9 
10 #if !defined(RXCPP_ON_IOS) && !defined(RXCPP_ON_ANDROID) && !defined(RXCPP_THREAD_LOCAL)
11 #if defined(_MSC_VER)
12 #define RXCPP_THREAD_LOCAL __declspec(thread)
13 #else
14 #define RXCPP_THREAD_LOCAL __thread
15 #endif
16 #endif
17 
18 #if !defined(RXCPP_DELETE)
19 #if defined(_MSC_VER)
20 #define RXCPP_DELETE __pragma(warning(disable: 4822)) =delete
21 #else
22 #define RXCPP_DELETE =delete
23 #endif
24 #endif
25 
26 #define RXCPP_CONCAT(Prefix, Suffix) Prefix ## Suffix
27 #define RXCPP_CONCAT_EVALUATE(Prefix, Suffix) RXCPP_CONCAT(Prefix, Suffix)
28 
29 #define RXCPP_MAKE_IDENTIFIER(Prefix) RXCPP_CONCAT_EVALUATE(Prefix, __LINE__)
30 
31 namespace rxcpp {
32 
33 namespace util {
34 
35 template<class T> using value_type_t = typename std::decay<T>::type::value_type;
36 template<class T> using decay_t = typename std::decay<T>::type;
37 template<class... TN> using result_of_t = typename std::result_of<TN...>::type;
38 
39 template<class T, std::size_t size>
40 std::vector<T> to_vector(const T (&arr) [size]) {
41  return std::vector<T>(std::begin(arr), std::end(arr));
42 }
43 
44 template<class T>
45 std::vector<T> to_vector(std::initializer_list<T> il) {
46  return std::vector<T>(il);
47 }
48 
49 template<class T0, class... TN>
50 typename std::enable_if<!std::is_array<T0>::value && std::is_pod<T0>::value, std::vector<T0>>::type to_vector(T0 t0, TN... tn) {
51  return to_vector({t0, tn...});
52 }
53 
54 template<class T, T... ValueN>
55 struct values {};
56 
57 template<class T, int Remaining, T Step = 1, T Cursor = 0, T... ValueN>
58 struct values_from;
59 
60 template<class T, T Step, T Cursor, T... ValueN>
61 struct values_from<T, 0, Step, Cursor, ValueN...>
62 {
63  typedef values<T, ValueN...> type;
64 };
65 
66 template<class T, int Remaining, T Step, T Cursor, T... ValueN>
67 struct values_from
68 {
69  typedef typename values_from<T, Remaining - 1, Step, Cursor + Step, ValueN..., Cursor>::type type;
70 };
71 
72 template<bool... BN>
73 struct all_true;
74 
75 template<bool B>
76 struct all_true<B>
77 {
78  static const bool value = B;
79 };
80 template<bool B, bool... BN>
81 struct all_true<B, BN...>
82 {
83  static const bool value = B && all_true<BN...>::value;
84 };
85 
86 template<bool... BN>
87 using enable_if_all_true_t = typename std::enable_if<all_true<BN...>::value>::type;
88 
89 template<class... BN>
91 
92 template<class B>
93 struct all_true_type<B>
94 {
95  static const bool value = B::value;
96 };
97 template<class B, class... BN>
98 struct all_true_type<B, BN...>
99 {
100  static const bool value = B::value && all_true_type<BN...>::value;
101 };
102 
103 template<class... BN>
104 using enable_if_all_true_type_t = typename std::enable_if<all_true_type<BN...>::value>::type;
105 
107  template<class... ValueN>
108  bool operator()(ValueN... vn) const;
109 
110  template<class Value0>
111  bool operator()(Value0 v0) const {
112  return v0;
113  }
114 
115  template<class Value0, class... ValueN>
116  bool operator()(Value0 v0, ValueN... vn) const {
117  return v0 && all_values_true()(vn...);
118  }
119 };
120 
122  template<class... ValueN>
123  bool operator()(ValueN... vn) const;
124 
125  template<class Value0>
126  bool operator()(Value0 v0) const {
127  return v0;
128  }
129 
130  template<class Value0, class... ValueN>
131  bool operator()(Value0 v0, ValueN... vn) const {
132  return v0 || any_value_true()(vn...);
133  }
134 };
135 
136 template<class... TN>
137 struct types {};
138 
139 //
140 // based on Walter Brown's void_t proposal
141 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3911.pdf
142 //
143 
144 struct types_checked {};
145 
146 namespace detail {
147 template<class... TN> struct types_checked_from {typedef types_checked type;};
148 }
149 
150 template<class... TN>
151 struct types_checked_from {typedef typename detail::types_checked_from<TN...>::type type;};
152 
153 template<class... TN>
154 using types_checked_t = typename types_checked_from<TN...>::type;
155 
156 
157 template<class Types, class =types_checked>
158 struct expand_value_types { struct type; };
159 template<class... TN>
160 struct expand_value_types<types<TN...>, types_checked_t<typename std::decay<TN>::type::value_type...>>
161 {
163 };
164 template<class... TN>
165 using value_types_t = typename expand_value_types<types<TN...>>::type;
166 
167 
168 template<class T, class C = types_checked>
169 struct value_type_from : public std::false_type {typedef types_checked type;};
170 
171 template<class T>
173  : public std::true_type {typedef value_type_t<T> type;};
174 
175 namespace detail {
176 template<class F, class... ParamN, int... IndexN>
177 auto apply(std::tuple<ParamN...> p, values<int, IndexN...>, F&& f)
178  -> decltype(f(std::forward<ParamN>(std::get<IndexN>(p))...)) {
179  return f(std::forward<ParamN>(std::get<IndexN>(p))...);
180 }
181 
182 template<class F_inner, class F_outer, class... ParamN, int... IndexN>
183 auto apply_to_each(std::tuple<ParamN...>& p, values<int, IndexN...>, F_inner& f_inner, F_outer& f_outer)
184  -> decltype(f_outer(std::move(f_inner(std::get<IndexN>(p)))...)) {
185  return f_outer(std::move(f_inner(std::get<IndexN>(p)))...);
186 }
187 
188 template<class F_inner, class F_outer, class... ParamN, int... IndexN>
189 auto apply_to_each(std::tuple<ParamN...>& p, values<int, IndexN...>, const F_inner& f_inner, const F_outer& f_outer)
190  -> decltype(f_outer(std::move(f_inner(std::get<IndexN>(p)))...)) {
191  return f_outer(std::move(f_inner(std::get<IndexN>(p)))...);
192 }
193 
194 }
195 template<class F, class... ParamN>
196 auto apply(std::tuple<ParamN...> p, F&& f)
197  -> decltype(detail::apply(std::move(p), typename values_from<int, sizeof...(ParamN)>::type(), std::forward<F>(f))) {
198  return detail::apply(std::move(p), typename values_from<int, sizeof...(ParamN)>::type(), std::forward<F>(f));
199 }
200 
201 template<class F_inner, class F_outer, class... ParamN>
202 auto apply_to_each(std::tuple<ParamN...>& p, F_inner& f_inner, F_outer& f_outer)
203  -> decltype(detail::apply_to_each(p, typename values_from<int, sizeof...(ParamN)>::type(), f_inner, f_outer)) {
204  return detail::apply_to_each(p, typename values_from<int, sizeof...(ParamN)>::type(), f_inner, f_outer);
205 }
206 
207 template<class F_inner, class F_outer, class... ParamN>
208 auto apply_to_each(std::tuple<ParamN...>& p, const F_inner& f_inner, const F_outer& f_outer)
209  -> decltype(detail::apply_to_each(p, typename values_from<int, sizeof...(ParamN)>::type(), f_inner, f_outer)) {
210  return detail::apply_to_each(p, typename values_from<int, sizeof...(ParamN)>::type(), f_inner, f_outer);
211 }
212 
213 namespace detail {
214 
215 template<class F>
216 struct apply_to
217 {
218  F to;
219 
220  explicit apply_to(F f)
221  : to(std::move(f))
222  {
223  }
224 
225  template<class... ParamN>
226  auto operator()(std::tuple<ParamN...> p)
227  -> decltype(rxcpp::util::apply(std::move(p), to)) {
228  return rxcpp::util::apply(std::move(p), to);
229  }
230  template<class... ParamN>
231  auto operator()(std::tuple<ParamN...> p) const
232  -> decltype(rxcpp::util::apply(std::move(p), to)) {
233  return rxcpp::util::apply(std::move(p), to);
234  }
235 };
236 
237 }
238 
239 template<class F>
240 auto apply_to(F f)
241  -> detail::apply_to<F> {
242  return detail::apply_to<F>(std::move(f));
243 }
244 
245 namespace detail {
246 
247 struct pack
248 {
249  template<class... ParamN>
250  auto operator()(ParamN... pn)
251  -> decltype(std::make_tuple(std::move(pn)...)) {
252  return std::make_tuple(std::move(pn)...);
253  }
254  template<class... ParamN>
255  auto operator()(ParamN... pn) const
256  -> decltype(std::make_tuple(std::move(pn)...)) {
257  return std::make_tuple(std::move(pn)...);
258  }
259 };
260 
261 }
262 
263 inline auto pack()
264  -> detail::pack {
265  return detail::pack();
266 }
267 
268 namespace detail {
269 
270 template<int Index>
271 struct take_at
272 {
273  template<class... ParamN>
274  auto operator()(ParamN... pn)
275  -> typename std::tuple_element<Index, std::tuple<decay_t<ParamN>...>>::type {
276  return std::get<Index>(std::make_tuple(std::move(pn)...));
277  }
278  template<class... ParamN>
279  auto operator()(ParamN... pn) const
280  -> typename std::tuple_element<Index, std::tuple<decay_t<ParamN>...>>::type {
281  return std::get<Index>(std::make_tuple(std::move(pn)...));
282  }
283 };
284 
285 }
286 
287 template<int Index>
288 inline auto take_at()
289  -> detail::take_at<Index> {
290  return detail::take_at<Index>();
291 }
292 
293 template <class D>
295 
296 template <template<class... TN> class Deferred, class... AN>
298 {
299  template<bool R>
300  struct tag_valid {static const bool valid = true; static const bool value = R;};
301  struct tag_not_valid {static const bool valid = false; static const bool value = false;};
302  typedef Deferred<typename resolve_type<AN>::type...> resolved_type;
303  template<class... CN>
304  static auto check(int) -> tag_valid<resolved_type::value>;
305  template<class... CN>
306  static tag_not_valid check(...);
307 
308  typedef decltype(check<AN...>(0)) tag_type;
309  static const bool valid = tag_type::valid;
310  static const bool value = tag_type::value;
311  static const bool not_value = valid && !value;
312 };
313 
314 template <template<class... TN> class Deferred, class... AN>
316 {
317  template<class R>
318  struct tag_valid {typedef R type; static const bool value = true;};
319  struct tag_not_valid {typedef void type; static const bool value = false;};
320  typedef Deferred<typename resolve_type<AN>::type...> resolved_type;
321  template<class... CN>
322  static auto check(int) -> tag_valid<resolved_type>;
323  template<class... CN>
324  static tag_not_valid check(...);
325 
326  typedef decltype(check<AN...>(0)) tag_type;
327  typedef typename tag_type::type type;
328  static const bool value = tag_type::value;
329 };
330 
331 template <template<class... TN> class Deferred, class... AN>
333 {
334  template<class R>
335  struct tag_valid {typedef R type; static const bool value = true;};
336  struct tag_not_valid {typedef void type; static const bool value = false;};
337  typedef Deferred<typename resolve_type<AN>::type...> resolved_type;
338  template<class... CN>
339  static auto check(int) -> tag_valid<value_type_t<resolved_type>>;
340  template<class... CN>
341  static tag_not_valid check(...);
342 
343  typedef decltype(check<AN...>(0)) tag_type;
344  typedef typename tag_type::type type;
345  static const bool value = tag_type::value;
346 };
347 
348 template <template<class... TN> class Deferred, class... AN>
350 {
351  template<class R>
352  struct tag_valid {typedef R type; static const bool value = true;};
353  struct tag_not_valid {typedef void type; static const bool value = false;};
354  typedef Deferred<typename resolve_type<AN>::type...> resolved_type;
355  template<class... CN>
356  static auto check(int) -> tag_valid<typename resolved_type::seed_type>;
357  template<class... CN>
358  static tag_not_valid check(...);
359 
360  typedef decltype(check<AN...>(0)) tag_type;
361  typedef typename tag_type::type type;
362  static const bool value = tag_type::value;
363 };
364 
365 template <class D>
366 struct resolve_type
367 {
368  typedef D type;
369 };
370 template <template<class... TN> class Deferred, class... AN>
371 struct resolve_type<defer_type<Deferred, AN...>>
372 {
373  typedef typename defer_type<Deferred, AN...>::type type;
374 };
375 template <template<class... TN> class Deferred, class... AN>
376 struct resolve_type<defer_value_type<Deferred, AN...>>
377 {
378  typedef typename defer_value_type<Deferred, AN...>::type type;
379 };
380 template <template<class... TN> class Deferred, class... AN>
381 struct resolve_type<defer_seed_type<Deferred, AN...>>
382 {
383  typedef typename defer_seed_type<Deferred, AN...>::type type;
384 };
385 
386 struct plus
387 {
388  template <class LHS, class RHS>
389  auto operator()(LHS&& lhs, RHS&& rhs) const
390  -> decltype(std::forward<LHS>(lhs) + std::forward<RHS>(rhs))
391  { return std::forward<LHS>(lhs) + std::forward<RHS>(rhs); }
392 };
393 
394 struct count
395 {
396  template <class T>
397  int operator()(int cnt, T&&) const
398  { return cnt + 1; }
399 };
400 
401 struct less
402 {
403  template <class LHS, class RHS>
404  auto operator()(LHS&& lhs, RHS&& rhs) const
405  -> decltype(std::forward<LHS>(lhs) < std::forward<RHS>(rhs))
406  { return std::forward<LHS>(lhs) < std::forward<RHS>(rhs); }
407 };
408 
409 template<class T = void>
410 struct equal_to
411 {
412  bool operator()(const T& lhs, const T& rhs) const { return lhs == rhs; }
413 };
414 
415 template<>
416 struct equal_to<void>
417 {
418  template<class LHS, class RHS>
419  auto operator()(LHS&& lhs, RHS&& rhs) const
420  -> decltype(std::forward<LHS>(lhs) == std::forward<RHS>(rhs))
421  { return std::forward<LHS>(lhs) == std::forward<RHS>(rhs); }
422 };
423 
424 namespace detail {
425 template<class OStream, class Delimit>
426 struct print_function
427 {
428  OStream& os;
429  Delimit delimit;
430  print_function(OStream& os, Delimit d) : os(os), delimit(std::move(d)) {}
431 
432  template<class... TN>
433  void operator()(const TN&... tn) const {
434  bool inserts[] = {(os << tn, true)...};
435  inserts[0] = *reinterpret_cast<bool*>(inserts); // silence warning
436  delimit();
437  }
438 
439  template<class... TN>
440  void operator()(const std::tuple<TN...>& tpl) const {
441  rxcpp::util::apply(tpl, *this);
442  }
443 };
444 
445 template<class OStream>
446 struct endline
447 {
448  OStream& os;
449  endline(OStream& os) : os(os) {}
450  void operator()() const {
451  os << std::endl;
452  }
453 private:
454  endline& operator=(const endline&) RXCPP_DELETE;
455 };
456 
457 template<class OStream, class ValueType>
458 struct insert_value
459 {
460  OStream& os;
461  ValueType value;
462  insert_value(OStream& os, ValueType v) : os(os), value(std::move(v)) {}
463  void operator()() const {
464  os << value;
465  }
466 private:
467  insert_value& operator=(const insert_value&) RXCPP_DELETE;
468 };
469 
470 template<class OStream, class Function>
471 struct insert_function
472 {
473  OStream& os;
474  Function call;
475  insert_function(OStream& os, Function f) : os(os), call(std::move(f)) {}
476  void operator()() const {
477  call(os);
478  }
479 private:
480  insert_function& operator=(const insert_function&) RXCPP_DELETE;
481 };
482 
483 template<class OStream, class Delimit>
484 auto print_followed_with(OStream& os, Delimit d)
485  -> detail::print_function<OStream, Delimit> {
486  return detail::print_function<OStream, Delimit>(os, std::move(d));
487 }
488 
489 }
490 
491 template<class OStream>
492 auto endline(OStream& os)
493  -> detail::endline<OStream> {
494  return detail::endline<OStream>(os);
495 }
496 
497 template<class OStream>
498 auto println(OStream& os)
499  -> decltype(detail::print_followed_with(os, endline(os))) {
500  return detail::print_followed_with(os, endline(os));
501 }
502 template<class OStream, class Delimit>
503 auto print_followed_with(OStream& os, Delimit d)
504  -> decltype(detail::print_followed_with(os, detail::insert_function<OStream, Delimit>(os, std::move(d)))) {
505  return detail::print_followed_with(os, detail::insert_function<OStream, Delimit>(os, std::move(d)));
506 }
507 template<class OStream, class DelimitValue>
508 auto print_followed_by(OStream& os, DelimitValue dv)
509  -> decltype(detail::print_followed_with(os, detail::insert_value<OStream, DelimitValue>(os, std::move(dv)))) {
510  return detail::print_followed_with(os, detail::insert_value<OStream, DelimitValue>(os, std::move(dv)));
511 }
512 
513 inline std::string what(std::exception_ptr ep) {
514  try {std::rethrow_exception(ep);}
515  catch (const std::exception& ex) {
516  return ex.what();
517  }
518  return std::string();
519 }
520 
521 namespace detail {
522 
523 template <class T>
524 class maybe
525 {
526  bool is_set;
527  typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type
528  storage;
529 public:
530  maybe()
531  : is_set(false)
532  {
533  }
534 
535  maybe(T value)
536  : is_set(false)
537  {
538  new (reinterpret_cast<T*>(&storage)) T(value);
539  is_set = true;
540  }
541 
542  maybe(const maybe& other)
543  : is_set(false)
544  {
545  if (other.is_set) {
546  new (reinterpret_cast<T*>(&storage)) T(other.get());
547  is_set = true;
548  }
549  }
550  maybe(maybe&& other)
551  : is_set(false)
552  {
553  if (other.is_set) {
554  new (reinterpret_cast<T*>(&storage)) T(std::move(other.get()));
555  is_set = true;
556  other.reset();
557  }
558  }
559 
560  ~maybe()
561  {
562  reset();
563  }
564 
565  typedef T value_type;
566  typedef T* iterator;
567  typedef const T* const_iterator;
568 
569  bool empty() const {
570  return !is_set;
571  }
572 
573  std::size_t size() const {
574  return is_set ? 1 : 0;
575  }
576 
577  iterator begin() {
578  return reinterpret_cast<T*>(&storage);
579  }
580  const_iterator begin() const {
581  return reinterpret_cast<T*>(&storage);
582  }
583 
584  iterator end() {
585  return reinterpret_cast<T*>(&storage) + size();
586  }
587  const_iterator end() const {
588  return reinterpret_cast<T*>(&storage) + size();
589  }
590 
591  T* operator->() {
592  if (!is_set) std::terminate();
593  return reinterpret_cast<T*>(&storage);
594  }
595  const T* operator->() const {
596  if (!is_set) std::terminate();
597  return reinterpret_cast<T*>(&storage);
598  }
599 
600  T& operator*() {
601  if (!is_set) std::terminate();
602  return *reinterpret_cast<T*>(&storage);
603  }
604  const T& operator*() const {
605  if (!is_set) std::terminate();
606  return *reinterpret_cast<T*>(&storage);
607  }
608 
609  T& get() {
610  if (!is_set) std::terminate();
611  return *reinterpret_cast<T*>(&storage);
612  }
613  const T& get() const {
614  if (!is_set) std::terminate();
615  return *reinterpret_cast<const T*>(&storage);
616  }
617 
618  void reset()
619  {
620  if (is_set) {
621  is_set = false;
622  reinterpret_cast<T*>(&storage)->~T();
623  //std::fill_n(reinterpret_cast<char*>(&storage), sizeof(T), 0);
624  }
625  }
626 
627  template<class U>
628  void reset(U&& value) {
629  reset();
630  new (reinterpret_cast<T*>(&storage)) T(std::forward<U>(value));
631  is_set = true;
632  }
633 
634  maybe& operator=(const T& other) {
635  reset(other);
636  return *this;
637  }
638  maybe& operator=(const maybe& other) {
639  if (!other.empty()) {
640  reset(other.get());
641  } else {
642  reset();
643  }
644  return *this;
645  }
646 };
647 
648 }
649 using detail::maybe;
650 
651 namespace detail {
652  struct surely
653  {
654  template<class... T>
655  auto operator()(T... t)
656  -> decltype(std::make_tuple(t.get()...)) {
657  return std::make_tuple(t.get()...);
658  }
659  template<class... T>
660  auto operator()(T... t) const
661  -> decltype(std::make_tuple(t.get()...)) {
662  return std::make_tuple(t.get()...);
663  }
664  };
665 }
666 
667 template<class... T>
668 inline auto surely(const std::tuple<T...>& tpl)
669  -> decltype(apply(tpl, detail::surely())) {
670  return apply(tpl, detail::surely());
671 }
672 
673 namespace detail {
674 
675 template<typename Function>
676 class unwinder
677 {
678 public:
679  ~unwinder()
680  {
681  if (!!function)
682  {
683  try {
684  (*function)();
685  } catch (...) {
686  std::unexpected();
687  }
688  }
689  }
690 
691  explicit unwinder(Function* functionArg)
692  : function(functionArg)
693  {
694  }
695 
696  void dismiss()
697  {
698  function = nullptr;
699  }
700 
701 private:
702  unwinder();
703  unwinder(const unwinder&);
704  unwinder& operator=(const unwinder&);
705 
706  Function* function;
707 };
708 
709 }
710 
711 #if !defined(RXCPP_THREAD_LOCAL)
712 template<typename T>
713 class thread_local_storage
714 {
715 private:
716  pthread_key_t key;
717 
718 public:
719  thread_local_storage()
720  {
721  pthread_key_create(&key, NULL);
722  }
723 
724  ~thread_local_storage()
725  {
726  pthread_key_delete(key);
727  }
728 
729  thread_local_storage& operator =(T* p)
730  {
731  pthread_setspecific(key, p);
732  return *this;
733  }
734 
735  bool operator !()
736  {
737  return pthread_getspecific(key) == NULL;
738  }
739 
740  T* operator ->()
741  {
742  return static_cast<T*>(pthread_getspecific(key));
743  }
744 
745  T* get()
746  {
747  return static_cast<T*>(pthread_getspecific(key));
748  }
749 };
750 #endif
751 
752 template<typename, typename C = types_checked>
753 struct is_string : std::false_type {
754 };
755 
756 template <typename T>
757 struct is_string<T,
758  typename types_checked_from<
759  typename T::value_type,
760  typename T::traits_type,
761  typename T::allocator_type>::type>
762  : std::is_base_of<
763  std::basic_string<
764  typename T::value_type,
765  typename T::traits_type,
766  typename T::allocator_type>, T> {
767 };
768 
769 namespace detail {
770 
771  template <class T, class = types_checked>
772  struct is_duration : std::false_type {};
773 
774  template <class T>
775  struct is_duration<T, types_checked_t<T, typename T::rep, typename T::period>>
776  : std::is_convertible<T*, std::chrono::duration<typename T::rep, typename T::period>*> {};
777 
778 }
779 
780 template <class T, class Decayed = decay_t<T>>
781 struct is_duration : detail::is_duration<Decayed> {};
782 
783 
784 // C++17 negation
785 namespace detail {
786  template<class T>
787  struct not_value : std::conditional<T::value, std::false_type, std::true_type>::type {
788  };
789 }
790 
791 template <class T>
792 struct negation : detail::not_value<T> {};
793 
794 }
795 namespace rxu=util;
796 
797 
798 //
799 // due to an noisy static_assert issue in more than one std lib impl,
800 // rxcpp maintains a whitelist filter for the types that are allowed
801 // to be hashed. this allows is_hashable<T> to work.
802 //
803 // NOTE: this should eventually be removed!
804 //
805 template <class T, typename = void>
807 
808 #if RXCPP_HASH_ENUM
809 template <class T>
810 struct filtered_hash<T, typename std::enable_if<std::is_enum<T>::value>::type> : std::hash<T> {
811 };
812 #elif RXCPP_HASH_ENUM_UNDERLYING
813 template <class T>
814 struct filtered_hash<T, typename std::enable_if<std::is_enum<T>::value>::type> : std::hash<typename std::underlying_type<T>::type> {
815 };
816 #endif
817 
818 template <class T>
819 struct filtered_hash<T, typename std::enable_if<std::is_integral<T>::value>::type> : std::hash<T> {
820 };
821 template <class T>
822 struct filtered_hash<T, typename std::enable_if<std::is_pointer<T>::value>::type> : std::hash<T> {
823 };
824 template <class T>
825 struct filtered_hash<T, typename std::enable_if<rxu::is_string<T>::value>::type> : std::hash<T> {
826 };
827 template <class T>
828 struct filtered_hash<T, typename std::enable_if<std::is_convertible<T, std::chrono::duration<typename T::rep, typename T::period>>::value>::type> {
829  using argument_type = T;
830  using result_type = std::size_t;
831 
833  {
834  return std::hash<typename argument_type::rep>{}(dur.count());
835  }
836 };
837 template <class T>
838 struct filtered_hash<T, typename std::enable_if<std::is_convertible<T, std::chrono::time_point<typename T::clock, typename T::duration>>::value>::type> {
839  using argument_type = T;
840  using result_type = std::size_t;
841 
843  {
844  return std::hash<typename argument_type::rep>{}(tp.time_since_epoch().count());
845  }
846 };
847 
848 template<typename, typename C = rxu::types_checked>
850  : std::false_type {};
851 
852 template<typename T>
853 struct is_hashable<T,
854  typename rxu::types_checked_from<
855  typename filtered_hash<T>::result_type,
856  typename filtered_hash<T>::argument_type,
857  typename std::result_of<filtered_hash<T>(T)>::type>::type>
858  : std::true_type {};
859 
860 }
861 
862 #define RXCPP_UNWIND(Name, Function) \
863  RXCPP_UNWIND_EXPLICIT(uwfunc_ ## Name, Name, Function)
864 
865 #define RXCPP_UNWIND_AUTO(Function) \
866  RXCPP_UNWIND_EXPLICIT(RXCPP_MAKE_IDENTIFIER(uwfunc_), RXCPP_MAKE_IDENTIFIER(unwind_), Function)
867 
868 #define RXCPP_UNWIND_EXPLICIT(FunctionName, UnwinderName, Function) \
869  auto FunctionName = (Function); \
870  rxcpp::util::detail::unwinder<decltype(FunctionName)> UnwinderName(std::addressof(FunctionName))
871 
872 #endif
typename std::enable_if< all_true< BN... >::value >::type enable_if_all_true_t
Definition: rx-util.hpp:87
void type
Definition: rx-util.hpp:336
Definition: rx-util.hpp:781
Definition: rx-util.hpp:151
Definition: rx-util.hpp:90
bool operator()(Value0 v0) const
Definition: rx-util.hpp:111
auto print_followed_with(OStream &os, Delimit d) -> decltype(detail::print_followed_with(os, detail::insert_function< OStream, Delimit >(os, std::move(d))))
Definition: rx-util.hpp:503
Definition: rx-util.hpp:169
tag_type::type type
Definition: rx-util.hpp:361
Definition: rx-util.hpp:318
Definition: rx-util.hpp:349
Definition: rx-all.hpp:26
Definition: rx-util.hpp:297
Definition: rx-util.hpp:158
typename std::decay< T >::type::value_type value_type_t
Definition: rx-util.hpp:35
std::vector< T > to_vector(const T(&arr) [size])
Definition: rx-util.hpp:40
Definition: rx-util.hpp:335
auto empty() -> decltype(from< T >())
Returns an observable that sends no items to observer and immediately completes, on the specified sch...
Definition: rx-empty.hpp:37
auto AN
Definition: rx-finally.hpp:105
Deferred< typename resolve_type< AN >::type... > resolved_type
Definition: rx-util.hpp:302
R type
Definition: rx-util.hpp:318
R type
Definition: rx-util.hpp:335
auto println(OStream &os) -> decltype(detail::print_followed_with(os, endline(os)))
Definition: rx-util.hpp:498
Definition: rx-util.hpp:849
typename std::decay< T >::type decay_t
Definition: rx-util.hpp:36
bool operator()(Value0 v0) const
Definition: rx-util.hpp:126
auto pack() -> detail::pack
Definition: rx-util.hpp:263
Definition: rx-util.hpp:332
tag_type::type type
Definition: rx-util.hpp:327
Definition: rx-util.hpp:806
Definition: rx-util.hpp:394
auto operator()(LHS &&lhs, RHS &&rhs) const -> decltype(std::forward< LHS >(lhs)==std::forward< RHS >(rhs))
Definition: rx-util.hpp:419
Definition: rx-util.hpp:352
Definition: rx-util.hpp:144
defer_seed_type< Deferred, AN... >::type type
Definition: rx-util.hpp:383
auto apply_to(F f) -> detail::apply_to< F >
Definition: rx-util.hpp:240
Definition: rx-util.hpp:386
typename std::enable_if< all_true_type< BN... >::value >::type enable_if_all_true_type_t
Definition: rx-util.hpp:104
Definition: rx-util.hpp:137
D type
Definition: rx-util.hpp:368
Definition: rx-util.hpp:315
defer_type< Deferred, AN... >::type type
Definition: rx-util.hpp:373
auto endline(OStream &os) -> detail::endline< OStream >
Definition: rx-util.hpp:492
Deferred< typename resolve_type< AN >::type... > resolved_type
Definition: rx-util.hpp:337
Deferred< typename resolve_type< AN >::type... > resolved_type
Definition: rx-util.hpp:354
auto surely(const std::tuple< T... > &tpl) -> decltype(apply(tpl, detail::surely()))
Definition: rx-util.hpp:668
void type
Definition: rx-util.hpp:319
bool operator()(Value0 v0, ValueN... vn) const
Definition: rx-util.hpp:131
int operator()(int cnt, T &&) const
Definition: rx-util.hpp:397
auto take_at() -> detail::take_at< Index >
Definition: rx-util.hpp:288
auto apply(std::tuple< ParamN... > p, F &&f) -> decltype(detail::apply(std::move(p), typename values_from< int, sizeof...(ParamN)>::type(), std::forward< F >(f)))
Definition: rx-util.hpp:196
Definition: rx-util.hpp:73
bool operator()(ValueN... vn) const
bool operator()(ValueN... vn) const
bool operator()(Value0 v0, ValueN... vn) const
Definition: rx-util.hpp:116
Definition: rx-util.hpp:319
Definition: rx-util.hpp:401
auto print_followed_by(OStream &os, DelimitValue dv) -> decltype(detail::print_followed_with(os, detail::insert_value< OStream, DelimitValue >(os, std::move(dv))))
Definition: rx-util.hpp:508
Definition: rx-util.hpp:294
typename types_checked_from< TN... >::type types_checked_t
Definition: rx-util.hpp:154
typename expand_value_types< types< TN... > >::type value_types_t
Definition: rx-util.hpp:165
bool operator()(const T &lhs, const T &rhs) const
Definition: rx-util.hpp:412
detail::types_checked_from< TN... >::type type
Definition: rx-util.hpp:151
values_from< T, Remaining - 1, Step, Cursor+Step, ValueN..., Cursor >::type type
Definition: rx-util.hpp:69
auto operator()(LHS &&lhs, RHS &&rhs) const -> decltype(std::forward< LHS >(lhs)+std::forward< RHS >(rhs))
Definition: rx-util.hpp:389
values< T, ValueN... > type
Definition: rx-util.hpp:63
tag_type::type type
Definition: rx-util.hpp:344
Definition: rx-util.hpp:300
Deferred< typename resolve_type< AN >::type... > resolved_type
Definition: rx-util.hpp:320
Definition: rx-util.hpp:55
Definition: rx-util.hpp:301
Definition: rx-util.hpp:410
Definition: rx-util.hpp:121
R type
Definition: rx-util.hpp:352
void type
Definition: rx-util.hpp:353
std::string what(std::exception_ptr ep)
Definition: rx-util.hpp:513
auto apply_to_each(std::tuple< ParamN... > &p, const F_inner &f_inner, const F_outer &f_outer) -> decltype(detail::apply_to_each(p, typename values_from< int, sizeof...(ParamN)>::type(), f_inner, f_outer))
Definition: rx-util.hpp:208
typename std::result_of< TN... >::type result_of_t
Definition: rx-util.hpp:37
defer_value_type< Deferred, AN... >::type type
Definition: rx-util.hpp:378
Definition: rx-util.hpp:792
Definition: rx-util.hpp:106
auto operator()(LHS &&lhs, RHS &&rhs) const -> decltype(std::forward< LHS >(lhs)< std::forward< RHS >(rhs))
Definition: rx-util.hpp:404
types_checked type
Definition: rx-util.hpp:169
Definition: rx-util.hpp:753
Definition: rx-util.hpp:58
auto apply_to_each(std::tuple< ParamN... > &p, F_inner &f_inner, F_outer &f_outer) -> decltype(detail::apply_to_each(p, typename values_from< int, sizeof...(ParamN)>::type(), f_inner, f_outer))
Definition: rx-util.hpp:202