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++.
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 #if !defined(CPPLINQ_LINQ_UTIL_HPP)
4 #define CPPLINQ_LINQ_UTIL_HPP
5 #pragma once
6 
7 namespace cpplinq { namespace util {
8 
9  template <class Container>
11  typedef typename Container::iterator iterator;
12  typedef typename std::iterator_traits<iterator>::value_type value_type;
13  typedef typename std::iterator_traits<iterator>::iterator_category iterator_category;
14 
15  // TODO: conservative definition for now.
17  std::is_reference<typename std::iterator_traits<iterator>::reference>::value
18  && std::is_same<typename std::remove_cv<value_type>::type,
19  typename std::remove_cv<typename std::remove_reference<typename std::iterator_traits<iterator>::reference>::type>::type>::value
20  };
21  };
22 
23  template <>
24  struct container_traits<int>;
25 
26  template <class Container>
27  struct container_traits<Container&>
29  {};
30  template <class Container>
31  struct container_traits<const Container>
32  : container_traits<Container>
33  {
34  typedef typename Container::const_iterator iterator;
35  };
36 
37  // Note: returns false if no partial order exists between two
38  // particular iterator categories, such as with some of the boost categories
39  template <class Cat1, class Cat2>
41  {
42  private:
43  typedef char yes;
44  typedef struct { char c1,c2; } no;
45  static yes invoke(Cat1);
46  static no invoke(...);
47  public:
48  enum { value = (sizeof(invoke(Cat2())) == sizeof(yes)) };
49  };
50 
51  // Return the weaker of the two iterator categories. Make sure
52  // a non-standard category is in the second argument position, as
53  // this metafunction will default to the first value if the order is undefined
54  template <class Cat1, class Cat2>
56  : std::conditional<
57  less_or_equal_iterator_category<Cat2, Cat1>::value,
58  Cat2,
59  Cat1>
60  {
61  };
62 
63 #if 0
64 #define CppLinq_GET_ITERATOR_TYPE(TContainer) \
65  decltype(begin(static_cast<TContainer*>(0)))
66 #define CppLinq_GET_CONST_ITERATOR_TYPE(TContainer) \
67  decltype(begin(static_cast<const TContainer*>(0)))
68 #else
69 #define CppLinq_GET_ITERATOR_TYPE(TContainer) \
70  typename ::cpplinq::util::container_traits<TContainer>::iterator
71 #define CppLinq_GET_CONST_ITERATOR_TYPE(TContainer) \
72  typename ::cpplinq::util::container_traits<TContainer>::const_iterator
73 #endif
74 
75  // VC10's std::tr1::result_of is busted with lambdas. use decltype instead on vc10 and later
76 #if defined(_MSC_VER) && _MSC_VER >= 1600
77  namespace detail {
78  template <class T> T instance();
79  };
80  template <class Fn> struct result_of;
81  template <class Fn>
82  struct result_of<Fn()> {
83  typedef decltype(detail::instance<Fn>()()) type;
84  };
85  template <class Fn, class A0>
86  struct result_of<Fn(A0)> {
87  typedef decltype(detail::instance<Fn>()(detail::instance<A0>())) type;
88  };
89  template <class Fn, class A0, class A1>
90  struct result_of<Fn(A0,A1)> {
91  typedef decltype(detail::instance<Fn>()(detail::instance<A0>(),
92  detail::instance<A1>())) type;
93  };
94  template <class Fn, class A0, class A1, class A2>
95  struct result_of<Fn(A0,A1,A2)> {
96  typedef decltype(detail::instance<Fn>()(detail::instance<A0>(),
97  detail::instance<A1>(),
98  detail::instance<A2>())) type;
99  };
100  template <class Fn, class A0, class A1, class A2, class A3>
101  struct result_of<Fn(A0,A1,A2,A3)> {
102  typedef decltype(detail::instance<Fn>()(detail::instance<A0>(),
103  detail::instance<A1>(),
104  detail::instance<A2>(),
105  detail::instance<A3>())) type;
106  };
107 #elif defined(_MSC_VER)
108  template <class T>
109  struct result_of<T> : std::tr1::result_of<T> {};
110 #else
111  using std::result_of;
112 #endif
113 
114  template<class Type>
115  struct identity
116  {
117  typedef Type type;
118  Type operator()(const Type& left) const {return left;}
119  };
120 
121  // faux pointer proxy for iterators that dereference to a value rather than reference, such as selectors
122  template <class T>
123  struct value_ptr
124  {
125  T value;
126  value_ptr(const T& value) : value(value)
127  {}
128  value_ptr(const T* pvalue) : value(*pvalue)
129  {}
130  const T* operator->()
131  {
132  return &value;
133  }
134  };
135 
136 
137  template <class T>
138  class maybe
139  {
140  bool is_set;
141  typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type
142  storage;
143  public:
145  : is_set(false)
146  {
147  }
148 
149  maybe(T value)
150  : is_set(false)
151  {
152  new (reinterpret_cast<T*>(&storage)) T(value);
153  is_set = true;
154  }
155 
156  maybe(const maybe& other)
157  : is_set(false)
158  {
159  if (other.is_set) {
160  new (reinterpret_cast<T*>(&storage)) T(*other.get());
161  is_set = true;
162  }
163  }
164  maybe(maybe&& other)
165  : is_set(false)
166  {
167  if (other.is_set) {
168  new (reinterpret_cast<T*>(&storage)) T(std::move(*other.get()));
169  is_set = true;
170  other.reset();
171  }
172  }
173 
175  {
176  reset();
177  }
178 
179  void reset()
180  {
181  if (is_set) {
182  is_set = false;
183  reinterpret_cast<T*>(&storage)->~T();
184  }
185  }
186 
187  T* get() {
188  return is_set ? reinterpret_cast<T*>(&storage) : 0;
189  }
190 
191  const T* get() const {
192  return is_set ? reinterpret_cast<const T*>(&storage) : 0;
193  }
194 
195  void set(T value) {
196  if (is_set) {
197  *reinterpret_cast<T*>(&storage) = std::move(value);
198  } else {
199  new (reinterpret_cast<T*>(&storage)) T(std::move(value));
200  is_set = true;
201  }
202  }
203 
204  T& operator*() { return *get(); }
205  const T& operator*() const { return *get(); }
206  T* operator->() { return get(); }
207  const T* operator->() const { return get(); }
208 
209  maybe& operator=(const T& other) {
210  set(other);
211  }
212  maybe& operator=(const maybe& other) {
213  if (const T* pother = other.get()) {
214  set(*pother);
215  } else {
216  reset();
217  }
218  return *this;
219  }
220 
221  // boolean-like operators
222  operator T*() { return get(); }
223  operator const T*() const { return get(); }
224 
225  private:
226 
227  };
228 }}
229 
230 
231 #endif //CPPLINQ_UTIL_HPP
232 
maybe & operator=(const maybe &other)
Definition: util.hpp:212
maybe(const maybe &other)
Definition: util.hpp:156
const T * operator->() const
Definition: util.hpp:207
Definition: util.hpp:123
Type type
Definition: util.hpp:117
Definition: util.hpp:138
std::iterator_traits< iterator >::value_type value_type
Definition: util.hpp:12
T & operator*()
Definition: util.hpp:204
maybe & operator=(const T &other)
Definition: util.hpp:209
std::iterator_traits< iterator >::iterator_category iterator_category
Definition: util.hpp:13
Type operator()(const Type &left) const
Definition: util.hpp:118
~maybe()
Definition: util.hpp:174
T * operator->()
Definition: util.hpp:206
maybe()
Definition: util.hpp:144
Definition: linq.hpp:186
const T & operator*() const
Definition: util.hpp:205
value_ptr(const T &value)
Definition: util.hpp:126
Definition: util.hpp:115
T * get()
Definition: util.hpp:187
Container::iterator iterator
Definition: util.hpp:11
Container::const_iterator iterator
Definition: util.hpp:34
maybe(T value)
Definition: util.hpp:149
Definition: util.hpp:10
maybe(maybe &&other)
Definition: util.hpp:164
void reset()
Definition: util.hpp:179
T value
Definition: util.hpp:125
const T * operator->()
Definition: util.hpp:130
value_ptr(const T *pvalue)
Definition: util.hpp:128