added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / table_ref.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_TABLE_REF_HPP
20 #define REALM_TABLE_REF_HPP
21
22 #include <cstddef>
23 #include <algorithm>
24
25 #include <realm/util/bind_ptr.hpp>
26
27 namespace realm {
28
29
30 class Table;
31
32
33 /// A reference-counting "smart pointer" for referring to table
34 /// accessors.
35 ///
36 /// The purpose of this smart pointer is to keep the referenced table
37 /// accessor alive for as long as anybody is referring to it, however,
38 /// for stack allocated table accessors, the lifetime is necessarily
39 /// determined by scope (see below).
40 ///
41 /// Please take note of the distinction between a "table" and a "table
42 /// accessor" here. A table accessor is an instance of `Table`,
43 /// and it may, or may not be attached to an
44 /// actual table at any specific point in time, but this state of
45 /// attachment of the accessor has nothing to do with the function of
46 /// the smart pointer. Also, in the rest of the documentation of this
47 /// class, whenever you see `Table::%foo`, you are supposed to read it
48 /// as, `Table::%foo`.
49 ///
50 ///
51 /// Table accessors are either created directly by an application via
52 /// a call to one of the public table constructors, or they are
53 /// created internally by the Realm library, such as when the
54 /// application calls Group::get_table(), Table::get_subtable(), or
55 /// Table::create().
56 ///
57 /// Applications can safely assume that all table accessors, created
58 /// internally by the Realm library, have a lifetime that is managed
59 /// by reference counting. This means that the application can prolong
60 /// the lifetime of *such* table accessors indefinitely by holding on
61 /// to at least one smart pointer, but note that the guarantee of the
62 /// continued existence of the accessor, does not imply that the
63 /// accessor remains attached to the underlying table (see
64 /// Table::is_attached() for details). Accessors whose lifetime are
65 /// controlled by reference counting are destroyed exactly when the
66 /// reference count drops to zero.
67 ///
68 /// When an application creates a new table accessor by a direct call
69 /// to one of the public constructors, the lifetime of that table
70 /// accessor is *not*, and cannot be managed by reference
71 /// counting. This is true regardless of the way the accessor is
72 /// created (i.e., regardless of whether it is an automatic variable
73 /// on the stack, or created on the heap using `new`). However, for
74 /// convenience, but with one important caveat, it is still possible
75 /// to use smart pointers to refer to such accessors. The caveat is
76 /// that no smart pointers are allowed to refer to the accessor at the
77 /// point in time when its destructor is called. It is entirely the
78 /// responsibility of the application to ensure that this requirement
79 /// is met. Failing to do so, will result in undefined
80 /// behavior. Finally, please note that an application is always free
81 /// to use Table::create() as an alternative to creating free-standing
82 /// top-level tables on the stack, and that this is indeed neccessary
83 /// when fully reference counted lifetimes are required.
84 ///
85 /// So, at any time, and for any table accessor, an application can
86 /// call Table::get_table_ref() to obtain a smart pointer that refers
87 /// to that table, however, while that is always possible and safe, it
88 /// is not always possible to extend the lifetime of an accessor by
89 /// holding on to a smart pointer. The question of whether that is
90 /// possible, depends directly on the way the accessor was created.
91 ///
92 ///
93 /// Apart from keeping track of the number of references, these smart
94 /// pointers behaves almost exactly like regular pointers. In
95 /// particular, it is possible to dereference a TableRef and get a
96 /// `Table&` out of it, however, if you are not careful, this can
97 /// easily lead to dangling references:
98 ///
99 /// \code{.cpp}
100 ///
101 ///   Table& sub_1 = *(table.get_subtable(0,0));
102 ///   sub_1.add_empty_row(); // Oops, sub_1 may be dangling!
103 ///
104 /// \endcode
105 ///
106 /// Whether `sub_1` is actually dangling in the example above will
107 /// depend on whether other references to the same subtable accessor
108 /// already exist, but it is never wise to rely in this. Here is a
109 /// safe and proper alternative:
110 ///
111 /// \code{.cpp}
112 ///
113 ///   TableRef sub_2 = table.get_subtable(0,0);
114 ///   sub_2.add_empty_row(); // Safe!
115 ///
116 ///   void do_something(Table&);
117 ///   do_something(*(table.get_subtable(0,0))); // Also safe!
118 ///
119 /// \endcode
120 ///
121 ///
122 /// \sa Table
123 /// \sa TableRef
124 template <class T>
125 class BasicTableRef : util::bind_ptr<T> {
126 public:
127     constexpr BasicTableRef() noexcept
128     {
129     }
130     ~BasicTableRef() noexcept
131     {
132     }
133
134     // Copy construct
135     BasicTableRef(const BasicTableRef& r) noexcept
136         : util::bind_ptr<T>(r)
137     {
138     }
139     template <class U>
140     BasicTableRef(const BasicTableRef<U>& r) noexcept
141         : util::bind_ptr<T>(r)
142     {
143     }
144
145     // Copy assign
146     BasicTableRef& operator=(const BasicTableRef&) noexcept;
147     template <class U>
148     BasicTableRef& operator=(const BasicTableRef<U>&) noexcept;
149
150     // Move construct
151     BasicTableRef(BasicTableRef&& r) noexcept
152         : util::bind_ptr<T>(std::move(r))
153     {
154     }
155     template <class U>
156     BasicTableRef(BasicTableRef<U>&& r) noexcept
157         : util::bind_ptr<T>(std::move(r))
158     {
159     }
160
161     // Move assign
162     BasicTableRef& operator=(BasicTableRef&&) noexcept;
163     template <class U>
164     BasicTableRef& operator=(BasicTableRef<U>&&) noexcept;
165
166     //@{
167     /// Comparison
168     template <class U>
169     bool operator==(const BasicTableRef<U>&) const noexcept;
170
171     template <class U>
172     bool operator==(U*) const noexcept;
173
174     template <class U>
175     bool operator!=(const BasicTableRef<U>&) const noexcept;
176
177     template <class U>
178     bool operator!=(U*) const noexcept;
179
180     template <class U>
181     bool operator<(const BasicTableRef<U>&) const noexcept;
182
183     template <class U>
184     bool operator<(U*) const noexcept;
185
186     template <class U>
187     bool operator>(const BasicTableRef<U>&) const noexcept;
188
189     template <class U>
190     bool operator>(U*) const noexcept;
191
192     template <class U>
193     bool operator<=(const BasicTableRef<U>&) const noexcept;
194
195     template <class U>
196     bool operator<=(U*) const noexcept;
197
198     template <class U>
199     bool operator>=(const BasicTableRef<U>&) const noexcept;
200
201     template <class U>
202     bool operator>=(U*) const noexcept;
203 //@}
204
205 // Dereference
206 #ifdef __clang__
207     // Clang has a bug that causes it to effectively ignore the 'using' declaration.
208     T& operator*() const noexcept
209     {
210         return util::bind_ptr<T>::operator*();
211     }
212 #else
213     using util::bind_ptr<T>::operator*;
214 #endif
215     using util::bind_ptr<T>::operator->;
216
217     using util::bind_ptr<T>::operator bool;
218
219     T* get() const noexcept
220     {
221         return util::bind_ptr<T>::get();
222     }
223     void reset() noexcept
224     {
225         util::bind_ptr<T>::reset();
226     }
227     void reset(T* t) noexcept
228     {
229         util::bind_ptr<T>::reset(t);
230     }
231
232     void swap(BasicTableRef& r) noexcept
233     {
234         this->util::bind_ptr<T>::swap(r);
235     }
236     friend void swap(BasicTableRef& a, BasicTableRef& b) noexcept
237     {
238         a.swap(b);
239     }
240
241     template <class U>
242     friend BasicTableRef<U> unchecked_cast(BasicTableRef<Table>) noexcept;
243
244     template <class U>
245     friend BasicTableRef<const U> unchecked_cast(BasicTableRef<const Table>) noexcept;
246
247 private:
248     template <class>
249     struct GetRowAccType {
250         typedef void type;
251     };
252
253     typedef typename GetRowAccType<T>::type RowAccessor;
254
255 public:
256     /// Same as 'table[i]' where 'table' is the referenced table.
257     RowAccessor operator[](size_t i) const noexcept
258     {
259         return (*this->get())[i];
260     }
261
262     explicit BasicTableRef(T* t) noexcept
263         : util::bind_ptr<T>(t)
264     {
265     }
266
267     T* release() { return util::bind_ptr<T>::release(); }
268 private:
269     friend class SubtableColumnBase;
270     friend class Table;
271     friend class Group;
272
273     template <class>
274     friend class BasicTableRef;
275
276     typedef typename util::bind_ptr<T>::casting_move_tag casting_move_tag;
277     template <class U>
278     BasicTableRef(BasicTableRef<U>* r, casting_move_tag) noexcept
279         : util::bind_ptr<T>(r, casting_move_tag())
280     {
281     }
282 };
283
284
285 typedef BasicTableRef<Table> TableRef;
286 typedef BasicTableRef<const Table> ConstTableRef;
287
288
289 template <class C, class T, class U>
290 inline std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& out, const BasicTableRef<U>& p)
291 {
292     out << static_cast<const void*>(&*p);
293     return out;
294 }
295
296 template <class T>
297 inline BasicTableRef<T> unchecked_cast(TableRef t) noexcept
298 {
299     return BasicTableRef<T>(&t, typename BasicTableRef<T>::casting_move_tag());
300 }
301
302 template <class T>
303 inline BasicTableRef<const T> unchecked_cast(ConstTableRef t) noexcept
304 {
305     return BasicTableRef<const T>(&t, typename BasicTableRef<T>::casting_move_tag());
306 }
307
308
309 //@{
310 /// Comparison
311 template <class T, class U>
312 bool operator==(T*, const BasicTableRef<U>&) noexcept;
313 template <class T, class U>
314 bool operator!=(T*, const BasicTableRef<U>&) noexcept;
315 template <class T, class U>
316 bool operator<(T*, const BasicTableRef<U>&) noexcept;
317 template <class T, class U>
318 bool operator>(T*, const BasicTableRef<U>&) noexcept;
319 template <class T, class U>
320 bool operator<=(T*, const BasicTableRef<U>&) noexcept;
321 template <class T, class U>
322 bool operator>=(T*, const BasicTableRef<U>&) noexcept;
323 //@}
324
325
326 // Implementation:
327
328 template <class T>
329 inline BasicTableRef<T>& BasicTableRef<T>::operator=(const BasicTableRef& r) noexcept
330 {
331     this->util::bind_ptr<T>::operator=(r);
332     return *this;
333 }
334
335 template <class T>
336 template <class U>
337 inline BasicTableRef<T>& BasicTableRef<T>::operator=(const BasicTableRef<U>& r) noexcept
338 {
339     this->util::bind_ptr<T>::operator=(r);
340     return *this;
341 }
342
343 template <class T>
344 inline BasicTableRef<T>& BasicTableRef<T>::operator=(BasicTableRef&& r) noexcept
345 {
346     this->util::bind_ptr<T>::operator=(std::move(r));
347     return *this;
348 }
349
350 template <class T>
351 template <class U>
352 inline BasicTableRef<T>& BasicTableRef<T>::operator=(BasicTableRef<U>&& r) noexcept
353 {
354     this->util::bind_ptr<T>::operator=(std::move(r));
355     return *this;
356 }
357
358 template <class T>
359 template <class U>
360 bool BasicTableRef<T>::operator==(const BasicTableRef<U>& p) const noexcept
361 {
362     return get() == p.get();
363 }
364
365 template <class T>
366 template <class U>
367 bool BasicTableRef<T>::operator==(U* p) const noexcept
368 {
369     return get() == p;
370 }
371
372 template <class T>
373 template <class U>
374 bool BasicTableRef<T>::operator!=(const BasicTableRef<U>& p) const noexcept
375 {
376     return get() != p.get();
377 }
378
379 template <class T>
380 template <class U>
381 bool BasicTableRef<T>::operator!=(U* p) const noexcept
382 {
383     return get() != p;
384 }
385
386 template <class T>
387 template <class U>
388 bool BasicTableRef<T>::operator<(const BasicTableRef<U>& p) const noexcept
389 {
390     return get() < p.get();
391 }
392
393 template <class T>
394 template <class U>
395 bool BasicTableRef<T>::operator<(U* p) const noexcept
396 {
397     return get() < p;
398 }
399
400 template <class T>
401 template <class U>
402 bool BasicTableRef<T>::operator>(const BasicTableRef<U>& p) const noexcept
403 {
404     return get() > p.get();
405 }
406
407 template <class T>
408 template <class U>
409 bool BasicTableRef<T>::operator>(U* p) const noexcept
410 {
411     return get() > p;
412 }
413
414 template <class T>
415 template <class U>
416 bool BasicTableRef<T>::operator<=(const BasicTableRef<U>& p) const noexcept
417 {
418     return get() <= p.get();
419 }
420
421 template <class T>
422 template <class U>
423 bool BasicTableRef<T>::operator<=(U* p) const noexcept
424 {
425     return get() <= p;
426 }
427
428 template <class T>
429 template <class U>
430 bool BasicTableRef<T>::operator>=(const BasicTableRef<U>& p) const noexcept
431 {
432     return get() >= p.get();
433 }
434
435 template <class T>
436 template <class U>
437 bool BasicTableRef<T>::operator>=(U* p) const noexcept
438 {
439     return get() >= p;
440 }
441
442 template <class T, class U>
443 bool operator==(T* a, const BasicTableRef<U>& b) noexcept
444 {
445     return b == a;
446 }
447
448 template <class T, class U>
449 bool operator!=(T* a, const BasicTableRef<U>& b) noexcept
450 {
451     return b != a;
452 }
453
454 template <class T, class U>
455 bool operator<(T* a, const BasicTableRef<U>& b) noexcept
456 {
457     return b > a;
458 }
459
460 template <class T, class U>
461 bool operator>(T* a, const BasicTableRef<U>& b) noexcept
462 {
463     return b < a;
464 }
465
466 template <class T, class U>
467 bool operator<=(T* a, const BasicTableRef<U>& b) noexcept
468 {
469     return b >= a;
470 }
471
472 template <class T, class U>
473 bool operator>=(T* a, const BasicTableRef<U>& b) noexcept
474 {
475     return b <= a;
476 }
477
478
479 } // namespace realm
480
481 #endif // REALM_TABLE_REF_HPP