added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / row.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_ROW_HPP
20 #define REALM_ROW_HPP
21
22 #include <cstdint>
23
24 #include <realm/util/type_traits.hpp>
25 #include <realm/mixed.hpp>
26 #include <realm/table_ref.hpp>
27 #include <realm/link_view_fwd.hpp>
28 #include <realm/handover_defs.hpp>
29
30 namespace realm {
31
32 template <class>
33 class BasicRow;
34
35
36 /// This class is a "mixin" and contains the common set of functions for several
37 /// distinct row-like classes.
38 ///
39 /// There is a direct and natural correspondance between the functions in this
40 /// class and functions in Table of the same name. For example:
41 ///
42 ///     table[i].get_int(j) == table.get_int(i,j)
43 ///
44 /// The effect of calling most of the row accessor functions on a detached
45 /// accessor is unspecified and may lead to general corruption, and/or a
46 /// crash. The exceptions are is_attached(), detach(), get_table(), get_index(),
47 /// and the destructor. Note however, that get_index() will still return an
48 /// unspecified value for a deatched accessor.
49 ///
50 /// When a row accessor is evaluated in a boolean context, it evaluates to true
51 /// if, and only if it is attached.
52 ///
53 /// \tparam T A const or non-const table type (currently either `Table` or
54 /// `const Table`).
55 ///
56 /// \tparam R A specific row accessor class (BasicRow or BasicRowExpr) providing
57 /// members `T* impl_get_table() const`, `size_t impl_get_row_ndx()
58 /// const`, and `void impl_detach()`. Neither are allowed to throw.
59 ///
60 /// \sa Table
61 /// \sa BasicRow
62 template <class T, class R>
63 class RowFuncs {
64 public:
65     typedef T table_type;
66
67     typedef BasicTableRef<const T> ConstTableRef;
68     typedef BasicTableRef<T> TableRef; // Same as ConstTableRef if `T` is 'const'
69
70     typedef typename util::CopyConst<T, LinkView>::type L;
71     using ConstLinkViewRef = std::shared_ptr<const L>;
72     using LinkViewRef = std::shared_ptr<L>; // Same as ConstLinkViewRef if `T` is 'const'
73
74     int_fast64_t get_int(size_t col_ndx) const noexcept;
75     bool get_bool(size_t col_ndx) const noexcept;
76     float get_float(size_t col_ndx) const noexcept;
77     double get_double(size_t col_ndx) const noexcept;
78     StringData get_string(size_t col_ndx) const noexcept;
79     BinaryData get_binary(size_t col_ndx) const noexcept;
80     OldDateTime get_olddatetime(size_t col_ndx) const noexcept;
81     Timestamp get_timestamp(size_t col_ndx) const noexcept;
82     ConstTableRef get_subtable(size_t col_ndx) const;
83     TableRef get_subtable(size_t col_ndx);
84     size_t get_subtable_size(size_t col_ndx) const noexcept;
85     size_t get_link(size_t col_ndx) const noexcept;
86     bool is_null_link(size_t col_ndx) const noexcept;
87     bool is_null(size_t col_ndx) const noexcept;
88     ConstLinkViewRef get_linklist(size_t col_ndx) const;
89     LinkViewRef get_linklist(size_t col_ndx);
90     bool linklist_is_empty(size_t col_ndx) const noexcept;
91     size_t get_link_count(size_t col_ndx) const noexcept;
92     Mixed get_mixed(size_t col_ndx) const noexcept;
93     DataType get_mixed_type(size_t col_ndx) const noexcept;
94
95     template <typename U>
96     U get(size_t col_ndx) const noexcept;
97
98     void set_int(size_t col_ndx, int_fast64_t value);
99     void set_int_unique(size_t col_ndx, int_fast64_t value);
100     void add_int(size_t col_ndx, int_fast64_t value);
101     void set_bool(size_t col_ndx, bool value);
102     void set_float(size_t col_ndx, float value);
103     void set_double(size_t col_ndx, double value);
104     void set_string(size_t col_ndx, StringData value);
105     void set_string_unique(size_t col_ndx, StringData value);
106     void set_binary(size_t col_ndx, BinaryData value);
107     void set_olddatetime(size_t col_ndx, OldDateTime value);
108     void set_timestamp(size_t col_ndx, Timestamp value);
109     void set_subtable(size_t col_ndx, const Table* value);
110     void set_link(size_t col_ndx, size_t value);
111     void nullify_link(size_t col_ndx);
112     void set_mixed(size_t col_ndx, Mixed value);
113     void set_mixed_subtable(size_t col_ndx, const Table* value);
114     void set_null(size_t col_ndx);
115     void set_null_unique(size_t col_ndx);
116
117     template <typename U>
118     void set(size_t col_ndx, U&& value, bool is_default = false);
119
120     template <typename U>
121     void set_unique(size_t col_ndx, U&& value);
122
123     void insert_substring(size_t col_ndx, size_t pos, StringData);
124     void remove_substring(size_t col_ndx, size_t pos, size_t size);
125
126     //@{
127     /// Note that these operations will cause the row accessor to be detached.
128     void remove();
129     void move_last_over();
130     //@}
131
132     size_t get_backlink_count() const noexcept;
133     size_t get_backlink_count(const Table& src_table, size_t src_col_ndx) const noexcept;
134     size_t get_backlink(const Table& src_table, size_t src_col_ndx, size_t backlink_ndx) const noexcept;
135
136     size_t get_column_count() const noexcept;
137     DataType get_column_type(size_t col_ndx) const noexcept;
138     StringData get_column_name(size_t col_ndx) const noexcept;
139     size_t get_column_index(StringData name) const noexcept;
140
141     /// Returns true if, and only if this accessor is currently attached to a
142     /// row.
143     ///
144     /// A row accesor may get detached from the underlying row for various
145     /// reasons (see below). When it does, it no longer refers to anything, and
146     /// can no longer be used, except for calling is_attached(), detach(),
147     /// get_table(), get_index(), and the destructor. The consequences of
148     /// calling other methods on a detached row accessor are unspecified. There
149     /// are a few Realm functions (Table::find_pkey_int()) that return a
150     /// detached row accessor to indicate a 'null' result. In all other cases,
151     /// however, row accessors obtained by calling functions in the Realm API
152     /// are always in the 'attached' state immediately upon return from those
153     /// functions.
154     ///
155     /// A row accessor becomes detached if the underlying row is removed, if the
156     /// associated table accessor becomes detached, or if the detach() method is
157     /// called. A row accessor does not become detached for any other reason.
158     bool is_attached() const noexcept;
159
160     /// Detach this accessor from the row it was attached to. This function has
161     /// no effect if the accessor was already detached (idempotency).
162     void detach() noexcept;
163
164     /// The table containing the row to which this accessor is currently
165     /// bound. For a detached accessor, the returned value is null.
166     const table_type* get_table() const noexcept;
167     table_type* get_table() noexcept;
168
169     /// The index of the row to which this accessor is currently bound. For a
170     /// detached accessor, the returned value is unspecified.
171     size_t get_index() const noexcept;
172
173     explicit operator bool() const noexcept;
174
175 private:
176     const T* table() const noexcept;
177     T* table() noexcept;
178     size_t row_ndx() const noexcept;
179 };
180
181
182 /// This class is a special kind of row accessor. It differes from a real row
183 /// accessor (BasicRow) by having a trivial and fast copy constructor and
184 /// descructor. It is supposed to be used as the return type of functions such
185 /// as Table::operator[](), and then to be used as a basis for constructing a
186 /// real row accessor. Objects of this class are intended to only ever exist as
187 /// temporaries.
188 ///
189 /// In contrast to a real row accessor (`BasicRow`), objects of this class do
190 /// not keep the parent table "alive", nor are they maintained (adjusted) across
191 /// row insertions and row removals like real row accessors are.
192 ///
193 /// \sa BasicRow
194 template <class T>
195 class BasicRowExpr : public RowFuncs<T, BasicRowExpr<T>> {
196 public:
197     BasicRowExpr() noexcept = default;
198
199     template <class U>
200     BasicRowExpr(const BasicRowExpr<U>&) noexcept;
201
202     template <class U>
203     BasicRowExpr(const BasicRow<U>&) noexcept;
204
205 private:
206     T* m_table = nullptr;       // nullptr if detached.
207     size_t m_row_ndx = 0; // Undefined if detached.
208
209     BasicRowExpr(T*, size_t init_row_ndx) noexcept;
210
211     T* impl_get_table() const noexcept;
212     size_t impl_get_row_ndx() const noexcept;
213     void impl_detach() noexcept;
214
215     // Make impl_get_table(), impl_get_row_ndx(), and impl_detach() accessible
216     // from RowFuncs.
217     friend class RowFuncs<T, BasicRowExpr<T>>;
218
219     // Make m_table and m_row_ndx accessible from BasicRowExpr(const
220     // BasicRowExpr<U>&) for any U.
221     template <class>
222     friend class BasicRowExpr;
223
224     // Make m_table and m_row_ndx accessible from
225     // BasicRow::BaicRow(BasicRowExpr<U>) for any U.
226     template <class>
227     friend class BasicRow;
228
229     // Make BasicRowExpr(T*, size_t) accessible from Table.
230     friend class Table;
231 };
232
233 // fwd decl
234 class Group;
235
236 class RowBase {
237 protected:
238     TableRef m_table; // nullptr if detached.
239     size_t m_row_ndx; // Undefined if detached.
240
241     void attach(Table*, size_t row_ndx) noexcept;
242     void reattach(Table*, size_t row_ndx) noexcept;
243     void impl_detach() noexcept;
244
245     RowBase()
246     {
247     }
248
249     RowBase(const RowBase&) = delete;
250     using HandoverPatch = RowBaseHandoverPatch;
251
252     RowBase(const RowBase& source, HandoverPatch& patch);
253
254 public:
255     static void generate_patch(const RowBase& source, HandoverPatch& patch);
256     void apply_patch(HandoverPatch& patch, Group& group);
257
258 private:
259     RowBase* m_prev = nullptr; // nullptr if first, undefined if detached.
260     RowBase* m_next = nullptr; // nullptr if last, undefined if detached.
261
262     // Table needs to be able to modify m_table and m_row_ndx.
263     friend class Table;
264 };
265
266
267 /// An accessor class for table rows (a.k.a. a "row accessor").
268 ///
269 /// For as long as it remains attached, a row accessor will keep the parent
270 /// table accessor alive. In case the lifetime of the parent table is not
271 /// managed by reference counting (such as when the table is an automatic
272 /// variable on the stack), the destruction of the table will cause all
273 /// remaining row accessors to be detached.
274 ///
275 /// While attached, a row accessor is bound to a particular row of the parent
276 /// table. If that row is removed, the accesssor becomes detached. If rows are
277 /// inserted or removed before it (at lower row index), then the accessor is
278 /// automatically adjusted to account for the change in index of the row to
279 /// which the accessor is bound. In other words, a row accessor is bound to the
280 /// contents of a row, not to a row index. See also is_attached().
281 ///
282 /// Row accessors are created and used as follows:
283 ///
284 ///     Row row       = table[7];  // 8th row of `table`
285 ///     ConstRow crow = ctable[2]; // 3rd row of const `ctable`
286 ///     Row first_row = table.front();
287 ///     Row last_row  = table.back();
288 ///
289 ///     float v = row.get_float(1); // Get the float in the 2nd column
290 ///     row.set_string(0, "foo");   // Update the string in the 1st column
291 ///
292 ///     Table* t = row.get_table();      // The parent table
293 ///     size_t i = row.get_index(); // The current row index
294 ///
295 /// \sa RowFuncs
296 template <class T>
297 class BasicRow : private RowBase, public RowFuncs<T, BasicRow<T>> {
298 public:
299     BasicRow() noexcept;
300
301     template <class U>
302     BasicRow(BasicRowExpr<U>) noexcept;
303
304     BasicRow(const BasicRow<T>&) noexcept;
305
306     template <class U>
307     BasicRow(const BasicRow<U>&) noexcept;
308
309     template <class U>
310     BasicRow& operator=(BasicRowExpr<U>) noexcept;
311
312     template <class U>
313     BasicRow& operator=(BasicRow<U>) noexcept;
314
315     BasicRow& operator=(const BasicRow<T>&) noexcept;
316
317     ~BasicRow() noexcept;
318
319 private:
320     T* impl_get_table() const noexcept;
321     size_t impl_get_row_ndx() const noexcept;
322
323     // Make impl_get_table(), impl_get_row_ndx(), and impl_detach() accessible
324     // from RowFuncs.
325     friend class RowFuncs<T, BasicRow<T>>;
326
327     // Make m_table and m_row_ndx accessible from BasicRow(const BasicRow<U>&)
328     // for any U.
329     template <class>
330     friend class BasicRow;
331
332     // Make m_table and m_row_ndx accessible from BasicRowExpr(const
333     // BasicRow<U>&) for any U.
334     template <class>
335     friend class BasicRowExpr;
336
337 public:
338     std::unique_ptr<BasicRow<T>> clone_for_handover(std::unique_ptr<HandoverPatch>& patch) const
339     {
340         patch.reset(new HandoverPatch);
341         std::unique_ptr<BasicRow<T>> retval(new BasicRow<T>(*this, *patch));
342         return retval;
343     }
344
345     static void generate_patch(const BasicRow& row, std::unique_ptr<HandoverPatch>& patch)
346     {
347         patch.reset(new HandoverPatch);
348         RowBase::generate_patch(row, *patch);
349     }
350
351     void apply_and_consume_patch(std::unique_ptr<HandoverPatch>& patch, Group& group)
352     {
353         apply_patch(*patch, group);
354         patch.reset();
355     }
356
357     void apply_patch(HandoverPatch& patch, Group& group)
358     {
359         RowBase::apply_patch(patch, group);
360     }
361
362 private:
363     BasicRow(const BasicRow<T>& source, HandoverPatch& patch)
364         : RowBase(source, patch)
365     {
366     }
367     friend class SharedGroup;
368 };
369
370 typedef BasicRow<Table> Row;
371 typedef BasicRow<const Table> ConstRow;
372
373
374 // Implementation
375
376 template <class T, class R>
377 inline int_fast64_t RowFuncs<T, R>::get_int(size_t col_ndx) const noexcept
378 {
379     return table()->get_int(col_ndx, row_ndx());
380 }
381
382 template <class T, class R>
383 inline bool RowFuncs<T, R>::get_bool(size_t col_ndx) const noexcept
384 {
385     return table()->get_bool(col_ndx, row_ndx());
386 }
387
388 template <class T, class R>
389 inline float RowFuncs<T, R>::get_float(size_t col_ndx) const noexcept
390 {
391     return table()->get_float(col_ndx, row_ndx());
392 }
393
394 template <class T, class R>
395 inline double RowFuncs<T, R>::get_double(size_t col_ndx) const noexcept
396 {
397     return table()->get_double(col_ndx, row_ndx());
398 }
399
400 template <class T, class R>
401 inline StringData RowFuncs<T, R>::get_string(size_t col_ndx) const noexcept
402 {
403     return table()->get_string(col_ndx, row_ndx());
404 }
405
406 template <class T, class R>
407 inline BinaryData RowFuncs<T, R>::get_binary(size_t col_ndx) const noexcept
408 {
409     return table()->get_binary(col_ndx, row_ndx());
410 }
411
412 template <class T, class R>
413 inline OldDateTime RowFuncs<T, R>::get_olddatetime(size_t col_ndx) const noexcept
414 {
415     return table()->get_olddatetime(col_ndx, row_ndx());
416 }
417
418 template <class T, class R>
419 inline Timestamp RowFuncs<T, R>::get_timestamp(size_t col_ndx) const noexcept
420 {
421     return table()->get_timestamp(col_ndx, row_ndx());
422 }
423
424 template <class T, class R>
425 inline typename RowFuncs<T, R>::ConstTableRef RowFuncs<T, R>::get_subtable(size_t col_ndx) const
426 {
427     return table()->get_subtable(col_ndx, row_ndx()); // Throws
428 }
429
430 template <class T, class R>
431 inline typename RowFuncs<T, R>::TableRef RowFuncs<T, R>::get_subtable(size_t col_ndx)
432 {
433     return table()->get_subtable(col_ndx, row_ndx()); // Throws
434 }
435
436 template <class T, class R>
437 inline size_t RowFuncs<T, R>::get_subtable_size(size_t col_ndx) const noexcept
438 {
439     return table()->get_subtable_size(col_ndx, row_ndx());
440 }
441
442 template <class T, class R>
443 inline size_t RowFuncs<T, R>::get_link(size_t col_ndx) const noexcept
444 {
445     return table()->get_link(col_ndx, row_ndx());
446 }
447
448 template <class T, class R>
449 inline bool RowFuncs<T, R>::is_null_link(size_t col_ndx) const noexcept
450 {
451     return table()->is_null_link(col_ndx, row_ndx());
452 }
453
454 template <class T, class R>
455 inline bool RowFuncs<T, R>::is_null(size_t col_ndx) const noexcept
456 {
457     return table()->is_null(col_ndx, row_ndx());
458 }
459
460 template <class T, class R>
461 inline typename RowFuncs<T, R>::ConstLinkViewRef RowFuncs<T, R>::get_linklist(size_t col_ndx) const
462 {
463     return table()->get_linklist(col_ndx, row_ndx()); // Throws
464 }
465
466 template <class T, class R>
467 inline typename RowFuncs<T, R>::LinkViewRef RowFuncs<T, R>::get_linklist(size_t col_ndx)
468 {
469     return table()->get_linklist(col_ndx, row_ndx()); // Throws
470 }
471
472 template <class T, class R>
473 inline bool RowFuncs<T, R>::linklist_is_empty(size_t col_ndx) const noexcept
474 {
475     return table()->linklist_is_empty(col_ndx, row_ndx());
476 }
477
478 template <class T, class R>
479 inline size_t RowFuncs<T, R>::get_link_count(size_t col_ndx) const noexcept
480 {
481     return table()->get_link_count(col_ndx, row_ndx());
482 }
483
484 template <class T, class R>
485 inline Mixed RowFuncs<T, R>::get_mixed(size_t col_ndx) const noexcept
486 {
487     return table()->get_mixed(col_ndx, row_ndx());
488 }
489
490 template <class T, class R>
491 inline DataType RowFuncs<T, R>::get_mixed_type(size_t col_ndx) const noexcept
492 {
493     return table()->get_mixed_type(col_ndx, row_ndx());
494 }
495
496 template <class T, class R>
497 template <class U>
498 inline U RowFuncs<T, R>::get(size_t col_ndx) const noexcept
499 {
500     return table()->template get<U>(col_ndx, row_ndx());
501 }
502
503 template <class T, class R>
504 inline void RowFuncs<T, R>::set_int(size_t col_ndx, int_fast64_t value)
505 {
506     table()->set_int(col_ndx, row_ndx(), value); // Throws
507 }
508
509 template <class T, class R>
510 inline void RowFuncs<T, R>::set_int_unique(size_t col_ndx, int_fast64_t value)
511 {
512     table()->set_int_unique(col_ndx, row_ndx(), value); // Throws
513 }
514
515 template <class T, class R>
516 inline void RowFuncs<T, R>::add_int(size_t col_ndx, int_fast64_t value)
517 {
518     table()->add_int(col_ndx, row_ndx(), value); // Throws
519 }
520
521 template <class T, class R>
522 inline void RowFuncs<T, R>::set_bool(size_t col_ndx, bool value)
523 {
524     table()->set_bool(col_ndx, row_ndx(), value); // Throws
525 }
526
527 template <class T, class R>
528 inline void RowFuncs<T, R>::set_float(size_t col_ndx, float value)
529 {
530     table()->set_float(col_ndx, row_ndx(), value); // Throws
531 }
532
533 template <class T, class R>
534 inline void RowFuncs<T, R>::set_double(size_t col_ndx, double value)
535 {
536     table()->set_double(col_ndx, row_ndx(), value); // Throws
537 }
538
539 template <class T, class R>
540 inline void RowFuncs<T, R>::set_string(size_t col_ndx, StringData value)
541 {
542     table()->set_string(col_ndx, row_ndx(), value); // Throws
543 }
544
545 template <class T, class R>
546 inline void RowFuncs<T, R>::set_string_unique(size_t col_ndx, StringData value)
547 {
548     table()->set_string_unique(col_ndx, row_ndx(), value); // Throws
549 }
550
551 template <class T, class R>
552 inline void RowFuncs<T, R>::set_binary(size_t col_ndx, BinaryData value)
553 {
554     table()->set_binary(col_ndx, row_ndx(), value); // Throws
555 }
556
557 template <class T, class R>
558 inline void RowFuncs<T, R>::set_olddatetime(size_t col_ndx, OldDateTime value)
559 {
560     table()->set_olddatetime(col_ndx, row_ndx(), value); // Throws
561 }
562
563 template <class T, class R>
564 inline void RowFuncs<T, R>::set_timestamp(size_t col_ndx, Timestamp value)
565 {
566     table()->set_timestamp(col_ndx, row_ndx(), value); // Throws
567 }
568
569 template <class T, class R>
570 inline void RowFuncs<T, R>::set_subtable(size_t col_ndx, const Table* value)
571 {
572     table()->set_subtable(col_ndx, row_ndx(), value); // Throws
573 }
574
575 template <class T, class R>
576 inline void RowFuncs<T, R>::set_link(size_t col_ndx, size_t value)
577 {
578     table()->set_link(col_ndx, row_ndx(), value); // Throws
579 }
580
581 template <class T, class R>
582 inline void RowFuncs<T, R>::nullify_link(size_t col_ndx)
583 {
584     table()->nullify_link(col_ndx, row_ndx()); // Throws
585 }
586
587 template <class T, class R>
588 inline void RowFuncs<T, R>::set_mixed(size_t col_ndx, Mixed value)
589 {
590     table()->set_mixed(col_ndx, row_ndx(), value); // Throws
591 }
592
593 template <class T, class R>
594 inline void RowFuncs<T, R>::set_mixed_subtable(size_t col_ndx, const Table* value)
595 {
596     table()->set_mixed_subtable(col_ndx, row_ndx(), value); // Throws
597 }
598
599 template <class T, class R>
600 inline void RowFuncs<T, R>::set_null(size_t col_ndx)
601 {
602     table()->set_null(col_ndx, row_ndx()); // Throws
603 }
604
605 template <class T, class R>
606 inline void RowFuncs<T, R>::set_null_unique(size_t col_ndx)
607 {
608     table()->set_null_unique(col_ndx, row_ndx()); // Throws
609 }
610
611 template <class T, class R>
612 template <class U>
613 inline void RowFuncs<T, R>::set(size_t col_ndx, U&& value, bool is_default)
614 {
615     table()->set(col_ndx, row_ndx(), std::forward<U>(value), is_default); // Throws
616 }
617
618 template <class T, class R>
619 template <class U>
620 inline void RowFuncs<T, R>::set_unique(size_t col_ndx, U&& value)
621 {
622     table()->set_unique(col_ndx, row_ndx(), std::forward<U>(value)); // Throws
623 }
624
625 template <class T, class R>
626 inline void RowFuncs<T, R>::insert_substring(size_t col_ndx, size_t pos, StringData value)
627 {
628     table()->insert_substring(col_ndx, row_ndx(), pos, value); // Throws
629 }
630
631 template <class T, class R>
632 inline void RowFuncs<T, R>::remove_substring(size_t col_ndx, size_t pos, size_t size)
633 {
634     table()->remove_substring(col_ndx, row_ndx(), pos, size); // Throws
635 }
636
637 template <class T, class R>
638 inline void RowFuncs<T, R>::remove()
639 {
640     table()->remove(row_ndx()); // Throws
641 }
642
643 template <class T, class R>
644 inline void RowFuncs<T, R>::move_last_over()
645 {
646     table()->move_last_over(row_ndx()); // Throws
647 }
648
649 template <class T, class R>
650 inline size_t RowFuncs<T, R>::get_backlink_count() const noexcept
651 {
652     return table()->get_backlink_count(row_ndx());
653 }
654
655 template <class T, class R>
656 inline size_t RowFuncs<T, R>::get_backlink_count(const Table& src_table, size_t src_col_ndx) const noexcept
657 {
658     return table()->get_backlink_count(row_ndx(), src_table, src_col_ndx);
659 }
660
661 template <class T, class R>
662 inline size_t RowFuncs<T, R>::get_backlink(const Table& src_table, size_t src_col_ndx, size_t backlink_ndx) const
663     noexcept
664 {
665     return table()->get_backlink(row_ndx(), src_table, src_col_ndx, backlink_ndx);
666 }
667
668 template <class T, class R>
669 inline size_t RowFuncs<T, R>::get_column_count() const noexcept
670 {
671     return table()->get_column_count();
672 }
673
674 template <class T, class R>
675 inline DataType RowFuncs<T, R>::get_column_type(size_t col_ndx) const noexcept
676 {
677     return table()->get_column_type(col_ndx);
678 }
679
680 template <class T, class R>
681 inline StringData RowFuncs<T, R>::get_column_name(size_t col_ndx) const noexcept
682 {
683     return table()->get_column_name(col_ndx);
684 }
685
686 template <class T, class R>
687 inline size_t RowFuncs<T, R>::get_column_index(StringData name) const noexcept
688 {
689     return table()->get_column_index(name);
690 }
691
692 template <class T, class R>
693 inline bool RowFuncs<T, R>::is_attached() const noexcept
694 {
695     return static_cast<const R*>(this)->impl_get_table();
696 }
697
698 template <class T, class R>
699 inline void RowFuncs<T, R>::detach() noexcept
700 {
701     static_cast<R*>(this)->impl_detach();
702 }
703
704 template <class T, class R>
705 inline const T* RowFuncs<T, R>::get_table() const noexcept
706 {
707     return table();
708 }
709
710 template <class T, class R>
711 inline T* RowFuncs<T, R>::get_table() noexcept
712 {
713     return table();
714 }
715
716 template <class T, class R>
717 inline size_t RowFuncs<T, R>::get_index() const noexcept
718 {
719     return row_ndx();
720 }
721
722 template <class T, class R>
723 inline RowFuncs<T, R>::operator bool() const noexcept
724 {
725     return is_attached();
726 }
727
728 template <class T, class R>
729 inline const T* RowFuncs<T, R>::table() const noexcept
730 {
731     return static_cast<const R*>(this)->impl_get_table();
732 }
733
734 template <class T, class R>
735 inline T* RowFuncs<T, R>::table() noexcept
736 {
737     return static_cast<R*>(this)->impl_get_table();
738 }
739
740 template <class T, class R>
741 inline size_t RowFuncs<T, R>::row_ndx() const noexcept
742 {
743     return static_cast<const R*>(this)->impl_get_row_ndx();
744 }
745
746
747 template <class T>
748 template <class U>
749 inline BasicRowExpr<T>::BasicRowExpr(const BasicRowExpr<U>& expr) noexcept
750     : m_table(expr.m_table)
751     , m_row_ndx(expr.m_row_ndx)
752 {
753 }
754
755 template <class T>
756 template <class U>
757 inline BasicRowExpr<T>::BasicRowExpr(const BasicRow<U>& row) noexcept
758     : m_table(row.m_table.get())
759     , m_row_ndx(row.m_row_ndx)
760 {
761 }
762
763 template <class T>
764 inline BasicRowExpr<T>::BasicRowExpr(T* init_table, size_t init_row_ndx) noexcept
765     : m_table(init_table)
766     , m_row_ndx(init_row_ndx)
767 {
768 }
769
770 template <class T>
771 inline T* BasicRowExpr<T>::impl_get_table() const noexcept
772 {
773     return m_table;
774 }
775
776 template <class T>
777 inline size_t BasicRowExpr<T>::impl_get_row_ndx() const noexcept
778 {
779     return m_row_ndx;
780 }
781
782 template <class T>
783 inline void BasicRowExpr<T>::impl_detach() noexcept
784 {
785     m_table = nullptr;
786 }
787
788
789 template <class T>
790 inline BasicRow<T>::BasicRow() noexcept
791 {
792 }
793
794 template <class T>
795 inline BasicRow<T>::BasicRow(const BasicRow<T>& row) noexcept
796     : RowBase()
797 {
798     attach(const_cast<Table*>(row.m_table.get()), row.m_row_ndx);
799 }
800
801 template <class T>
802 template <class U>
803 inline BasicRow<T>::BasicRow(BasicRowExpr<U> expr) noexcept
804 {
805     T* expr_table = expr.m_table; // Check that pointer types are compatible
806     attach(const_cast<Table*>(expr_table), expr.m_row_ndx);
807 }
808
809 template <class T>
810 template <class U>
811 inline BasicRow<T>::BasicRow(const BasicRow<U>& row) noexcept
812 {
813     T* row_table = row.m_table.get(); // Check that pointer types are compatible
814     attach(const_cast<Table*>(row_table), row.m_row_ndx);
815 }
816
817 template <class T>
818 template <class U>
819 inline BasicRow<T>& BasicRow<T>::operator=(BasicRowExpr<U> expr) noexcept
820 {
821     T* expr_table = expr.m_table; // Check that pointer types are compatible
822     reattach(const_cast<Table*>(expr_table), expr.m_row_ndx);
823     return *this;
824 }
825
826 template <class T>
827 template <class U>
828 inline BasicRow<T>& BasicRow<T>::operator=(BasicRow<U> row) noexcept
829 {
830     T* row_table = row.m_table.get(); // Check that pointer types are compatible
831     reattach(const_cast<Table*>(row_table), row.m_row_ndx);
832     return *this;
833 }
834
835 template <class T>
836 inline BasicRow<T>& BasicRow<T>::operator=(const BasicRow<T>& row) noexcept
837 {
838     reattach(const_cast<Table*>(row.m_table.get()), row.m_row_ndx);
839     return *this;
840 }
841
842 template <class T>
843 inline BasicRow<T>::~BasicRow() noexcept
844 {
845     RowBase::impl_detach();
846 }
847
848 template <class T>
849 inline T* BasicRow<T>::impl_get_table() const noexcept
850 {
851     return m_table.get();
852 }
853
854 template <class T>
855 inline size_t BasicRow<T>::impl_get_row_ndx() const noexcept
856 {
857     return m_row_ndx;
858 }
859
860 } // namespace realm
861
862 #endif // REALM_ROW_HPP