PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/icndb/Pods/Headers/Private/Realm/realm/table_ref.hpp

https://gitlab.com/Tj3n123/ios-icndb-app
C++ Header | 473 lines | 263 code | 77 blank | 133 comment | 6 complexity | 1cb663c6dd9269e4f38faf2c79838ae6 MD5 | raw file
  1. /*************************************************************************
  2. *
  3. * REALM CONFIDENTIAL
  4. * __________________
  5. *
  6. * [2011] - [2012] Realm Inc
  7. * All Rights Reserved.
  8. *
  9. * NOTICE: All information contained herein is, and remains
  10. * the property of Realm Incorporated and its suppliers,
  11. * if any. The intellectual and technical concepts contained
  12. * herein are proprietary to Realm Incorporated
  13. * and its suppliers and may be covered by U.S. and Foreign Patents,
  14. * patents in process, and are protected by trade secret or copyright law.
  15. * Dissemination of this information or reproduction of this material
  16. * is strictly forbidden unless prior written permission is obtained
  17. * from Realm Incorporated.
  18. *
  19. **************************************************************************/
  20. #ifndef REALM_TABLE_REF_HPP
  21. #define REALM_TABLE_REF_HPP
  22. #include <cstddef>
  23. #include <algorithm>
  24. #include <realm/util/bind_ptr.hpp>
  25. namespace realm {
  26. class Table;
  27. template<class>
  28. class BasicTable;
  29. /// A reference-counting "smart pointer" for referring to table
  30. /// accessors.
  31. ///
  32. /// The purpose of this smart pointer is to keep the referenced table
  33. /// accessor alive for as long as anybody is referring to it, however,
  34. /// for stack allocated table accessors, the lifetime is necessarily
  35. /// determined by scope (see below).
  36. ///
  37. /// Please take note of the distinction between a "table" and a "table
  38. /// accessor" here. A table accessor is an instance of `Table` or
  39. /// `BasicTable<Spec>`, and it may, or may not be attached to an
  40. /// actual table at any specific point in time, but this state of
  41. /// attachment of the accessor has nothing to do with the function of
  42. /// the smart pointer. Also, in the rest of the documentation of this
  43. /// class, whenever you see `Table::foo`, you are supposed to read it
  44. /// as, `Table::foo` or `BasicTable<Spec>::foo`.
  45. ///
  46. ///
  47. /// Table accessors are either created directly by an application via
  48. /// a call to one of the public table constructors, or they are
  49. /// created internally by the Realm library, such as when the
  50. /// application calls Group::get_table(), Table::get_subtable(), or
  51. /// Table::create().
  52. ///
  53. /// Applications can safely assume that all table accessors, created
  54. /// internally by the Realm library, have a lifetime that is managed
  55. /// by reference counting. This means that the application can prolong
  56. /// the lifetime of *such* table accessors indefinitely by holding on
  57. /// to at least one smart pointer, but note that the guarantee of the
  58. /// continued existence of the accessor, does not imply that the
  59. /// accessor remains attached to the underlying table (see
  60. /// Table::is_attached() for details). Accessors whose lifetime are
  61. /// controlled by reference counting are destroyed exactly when the
  62. /// reference count drops to zero.
  63. ///
  64. /// When an application creates a new table accessor by a direct call
  65. /// to one of the public constructors, the lifetime of that table
  66. /// accessor is *not*, and cannot be managed by reference
  67. /// counting. This is true regardless of the way the accessor is
  68. /// created (i.e., regardless of whether it is an automatic variable
  69. /// on the stack, or created on the heap using `new`). However, for
  70. /// convenience, but with one important caveat, it is still possible
  71. /// to use smart pointers to refer to such accessors. The caveat is
  72. /// that no smart pointers are allowed to refer to the accessor at the
  73. /// point in time when its destructor is called. It is entirely the
  74. /// responsibility of the application to ensure that this requirement
  75. /// is met. Failing to do so, will result in undefined
  76. /// behavior. Finally, please note that an application is always free
  77. /// to use Table::create() as an alternative to creating free-standing
  78. /// top-level tables on the stack, and that this is indeed neccessary
  79. /// when fully reference counted lifetimes are required.
  80. ///
  81. /// So, at any time, and for any table accessor, an application can
  82. /// call Table::get_table_ref() to obtain a smart pointer that refers
  83. /// to that table, however, while that is always possible and safe, it
  84. /// is not always possible to extend the lifetime of an accessor by
  85. /// holding on to a smart pointer. The question of whether that is
  86. /// possible, depends directly on the way the accessor was created.
  87. ///
  88. ///
  89. /// Apart from keeping track of the number of references, these smart
  90. /// pointers behaves almost exactly like regular pointers. In
  91. /// particular, it is possible to dereference a TableRef and get a
  92. /// `Table&` out of it, however, if you are not careful, this can
  93. /// easily lead to dangling references:
  94. ///
  95. /// \code{.cpp}
  96. ///
  97. /// Table& sub_1 = *(table.get_subtable(0,0));
  98. /// sub_1.add_empty_row(); // Oops, sub_1 may be dangling!
  99. ///
  100. /// \endcode
  101. ///
  102. /// Whether `sub_1` is actually dangling in the example above will
  103. /// depend on whether other references to the same subtable accessor
  104. /// already exist, but it is never wise to rely in this. Here is a
  105. /// safe and proper alternative:
  106. ///
  107. /// \code{.cpp}
  108. ///
  109. /// TableRef sub_2 = table.get_subtable(0,0);
  110. /// sub_2.add_empty_row(); // Safe!
  111. ///
  112. /// void do_something(Table&);
  113. /// do_something(*(table.get_subtable(0,0))); // Also safe!
  114. ///
  115. /// \endcode
  116. ///
  117. ///
  118. /// This class provides a form of move semantics that is compatible
  119. /// with C++03. It is similar to, but not as powerful as what is
  120. /// provided natively by C++11. Instead of using `std::move()` (in
  121. /// C++11), one must use `move()` without qualification. This will
  122. /// call a special function that is a friend of this class. The
  123. /// effectiveness of this form of move semantics relies on 'return
  124. /// value optimization' being enabled in the compiler.
  125. ///
  126. /// \sa Table
  127. /// \sa TableRef
  128. template<class T>
  129. class BasicTableRef: util::bind_ptr<T> {
  130. public:
  131. constexpr BasicTableRef() noexcept {}
  132. ~BasicTableRef() noexcept {}
  133. // Copy construct
  134. BasicTableRef(const BasicTableRef& r) noexcept: util::bind_ptr<T>(r) {}
  135. template<class U>
  136. BasicTableRef(const BasicTableRef<U>& r) noexcept:
  137. util::bind_ptr<T>(r) {}
  138. // Copy assign
  139. BasicTableRef& operator=(const BasicTableRef&) noexcept;
  140. template<class U>
  141. BasicTableRef& operator=(const BasicTableRef<U>&) noexcept;
  142. // Move construct
  143. BasicTableRef(BasicTableRef&& r) noexcept: util::bind_ptr<T>(std::move(r)) {}
  144. template<class U>
  145. BasicTableRef(BasicTableRef<U>&& r) noexcept:
  146. util::bind_ptr<T>(std::move(r)) {}
  147. // Move assign
  148. BasicTableRef& operator=(BasicTableRef&&) noexcept;
  149. template<class U>
  150. BasicTableRef& operator=(BasicTableRef<U>&&) noexcept;
  151. // Replacement for std::move() in C++03
  152. friend BasicTableRef move(BasicTableRef& r) noexcept
  153. {
  154. return BasicTableRef(&r, move_tag());
  155. }
  156. //@{
  157. /// Comparison
  158. template<class U>
  159. bool operator==(const BasicTableRef<U>&) const noexcept;
  160. template<class U>
  161. bool operator==(U*) const noexcept;
  162. template<class U>
  163. bool operator!=(const BasicTableRef<U>&) const noexcept;
  164. template<class U>
  165. bool operator!=(U*) const noexcept;
  166. template<class U>
  167. bool operator<(const BasicTableRef<U>&) const noexcept;
  168. template<class U>
  169. bool operator<(U*) const noexcept;
  170. template<class U>
  171. bool operator>(const BasicTableRef<U>&) const noexcept;
  172. template<class U>
  173. bool operator>(U*) const noexcept;
  174. template<class U>
  175. bool operator<=(const BasicTableRef<U>&) const noexcept;
  176. template<class U>
  177. bool operator<=(U*) const noexcept;
  178. template<class U>
  179. bool operator>=(const BasicTableRef<U>&) const noexcept;
  180. template<class U>
  181. bool operator>=(U*) const noexcept;
  182. //@}
  183. // Dereference
  184. #ifdef __clang__
  185. // Clang has a bug that causes it to effectively ignore the 'using' declaration.
  186. T& operator*() const noexcept { return util::bind_ptr<T>::operator*(); }
  187. #else
  188. using util::bind_ptr<T>::operator*;
  189. #endif
  190. using util::bind_ptr<T>::operator->;
  191. using util::bind_ptr<T>::operator bool;
  192. T* get() const noexcept { return util::bind_ptr<T>::get(); }
  193. void reset() noexcept { util::bind_ptr<T>::reset(); }
  194. void reset(T* t) noexcept { util::bind_ptr<T>::reset(t); }
  195. void swap(BasicTableRef& r) noexcept { this->util::bind_ptr<T>::swap(r); }
  196. friend void swap(BasicTableRef& a, BasicTableRef& b) noexcept { a.swap(b); }
  197. template<class U>
  198. friend BasicTableRef<U> unchecked_cast(BasicTableRef<Table>) noexcept;
  199. template<class U>
  200. friend BasicTableRef<const U> unchecked_cast(BasicTableRef<const Table>) noexcept;
  201. private:
  202. template<class>
  203. struct GetRowAccType { typedef void type; };
  204. template<class Spec>
  205. struct GetRowAccType<BasicTable<Spec>> {
  206. typedef typename BasicTable<Spec>::RowAccessor type;
  207. };
  208. template<class Spec>
  209. struct GetRowAccType<const BasicTable<Spec>> {
  210. typedef typename BasicTable<Spec>::ConstRowAccessor type;
  211. };
  212. typedef typename GetRowAccType<T>::type RowAccessor;
  213. public:
  214. /// Same as 'table[i]' where 'table' is the referenced table.
  215. RowAccessor operator[](size_t i) const noexcept { return (*this->get())[i]; }
  216. private:
  217. friend class SubtableColumnBase;
  218. friend class Table;
  219. friend class Group;
  220. template<class>
  221. friend class BasicTable;
  222. template<class>
  223. friend class BasicTableRef;
  224. explicit BasicTableRef(T* t) noexcept: util::bind_ptr<T>(t) {}
  225. typedef typename util::bind_ptr<T>::move_tag move_tag;
  226. BasicTableRef(BasicTableRef* r, move_tag) noexcept:
  227. util::bind_ptr<T>(r, move_tag()) {}
  228. typedef typename util::bind_ptr<T>::casting_move_tag casting_move_tag;
  229. template<class U>
  230. BasicTableRef(BasicTableRef<U>* r, casting_move_tag) noexcept:
  231. util::bind_ptr<T>(r, casting_move_tag()) {}
  232. };
  233. typedef BasicTableRef<Table> TableRef;
  234. typedef BasicTableRef<const Table> ConstTableRef;
  235. template<class C, class T, class U>
  236. inline std::basic_ostream<C,T>& operator<<(std::basic_ostream<C,T>& out, const BasicTableRef<U>& p)
  237. {
  238. out << static_cast<const void*>(&*p);
  239. return out;
  240. }
  241. template<class T>
  242. inline BasicTableRef<T> unchecked_cast(TableRef t) noexcept
  243. {
  244. return BasicTableRef<T>(&t, typename BasicTableRef<T>::casting_move_tag());
  245. }
  246. template<class T>
  247. inline BasicTableRef<const T> unchecked_cast(ConstTableRef t) noexcept
  248. {
  249. return BasicTableRef<const T>(&t, typename BasicTableRef<T>::casting_move_tag());
  250. }
  251. //@{
  252. /// Comparison
  253. template<class T, class U>
  254. bool operator==(T*, const BasicTableRef<U>&) noexcept;
  255. template<class T, class U>
  256. bool operator!=(T*, const BasicTableRef<U>&) noexcept;
  257. template<class T, class U>
  258. bool operator<(T*, const BasicTableRef<U>&) noexcept;
  259. template<class T, class U>
  260. bool operator>(T*, const BasicTableRef<U>&) noexcept;
  261. template<class T, class U>
  262. bool operator<=(T*, const BasicTableRef<U>&) noexcept;
  263. template<class T, class U>
  264. bool operator>=(T*, const BasicTableRef<U>&) noexcept;
  265. //@}
  266. // Implementation:
  267. template<class T>
  268. inline BasicTableRef<T>& BasicTableRef<T>::operator=(const BasicTableRef& r) noexcept
  269. {
  270. this->util::bind_ptr<T>::operator=(r);
  271. return *this;
  272. }
  273. template<class T>
  274. template<class U>
  275. inline BasicTableRef<T>& BasicTableRef<T>::operator=(const BasicTableRef<U>& r) noexcept
  276. {
  277. this->util::bind_ptr<T>::operator=(r);
  278. return *this;
  279. }
  280. template<class T>
  281. inline BasicTableRef<T>& BasicTableRef<T>::operator=(BasicTableRef&& r) noexcept
  282. {
  283. this->util::bind_ptr<T>::operator=(std::move(r));
  284. return *this;
  285. }
  286. template<class T>
  287. template<class U>
  288. inline BasicTableRef<T>& BasicTableRef<T>::operator=(BasicTableRef<U>&& r) noexcept
  289. {
  290. this->util::bind_ptr<T>::operator=(std::move(r));
  291. return *this;
  292. }
  293. template<class T>
  294. template<class U>
  295. bool BasicTableRef<T>::operator==(const BasicTableRef<U>& p) const noexcept
  296. {
  297. return get() == p.get();
  298. }
  299. template<class T>
  300. template<class U>
  301. bool BasicTableRef<T>::operator==(U* p) const noexcept
  302. {
  303. return get() == p;
  304. }
  305. template<class T>
  306. template<class U>
  307. bool BasicTableRef<T>::operator!=(const BasicTableRef<U>& p) const noexcept
  308. {
  309. return get() != p.get();
  310. }
  311. template<class T>
  312. template<class U>
  313. bool BasicTableRef<T>::operator!=(U* p) const noexcept
  314. {
  315. return get() != p;
  316. }
  317. template<class T>
  318. template<class U>
  319. bool BasicTableRef<T>::operator<(const BasicTableRef<U>& p) const noexcept
  320. {
  321. return get() < p.get();
  322. }
  323. template<class T>
  324. template<class U>
  325. bool BasicTableRef<T>::operator<(U* p) const noexcept
  326. {
  327. return get() < p;
  328. }
  329. template<class T>
  330. template<class U>
  331. bool BasicTableRef<T>::operator>(const BasicTableRef<U>& p) const noexcept
  332. {
  333. return get() > p.get();
  334. }
  335. template<class T>
  336. template<class U>
  337. bool BasicTableRef<T>::operator>(U* p) const noexcept
  338. {
  339. return get() > p;
  340. }
  341. template<class T>
  342. template<class U>
  343. bool BasicTableRef<T>::operator<=(const BasicTableRef<U>& p) const noexcept
  344. {
  345. return get() <= p.get();
  346. }
  347. template<class T>
  348. template<class U>
  349. bool BasicTableRef<T>::operator<=(U* p) const noexcept
  350. {
  351. return get() <= p;
  352. }
  353. template<class T>
  354. template<class U>
  355. bool BasicTableRef<T>::operator>=(const BasicTableRef<U>& p) const noexcept
  356. {
  357. return get() >= p.get();
  358. }
  359. template<class T>
  360. template<class U>
  361. bool BasicTableRef<T>::operator>=(U* p) const noexcept
  362. {
  363. return get() >= p;
  364. }
  365. template<class T, class U>
  366. bool operator==(T* a, const BasicTableRef<U>& b) noexcept
  367. {
  368. return b == a;
  369. }
  370. template<class T, class U>
  371. bool operator!=(T* a, const BasicTableRef<U>& b) noexcept
  372. {
  373. return b != a;
  374. }
  375. template<class T, class U>
  376. bool operator<(T* a, const BasicTableRef<U>& b) noexcept
  377. {
  378. return b > a;
  379. }
  380. template<class T, class U>
  381. bool operator>(T* a, const BasicTableRef<U>& b) noexcept
  382. {
  383. return b < a;
  384. }
  385. template<class T, class U>
  386. bool operator<=(T* a, const BasicTableRef<U>& b) noexcept
  387. {
  388. return b >= a;
  389. }
  390. template<class T, class U>
  391. bool operator>=(T* a, const BasicTableRef<U>& b) noexcept
  392. {
  393. return b <= a;
  394. }
  395. } // namespace realm
  396. #endif // REALM_TABLE_REF_HPP