1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 **************************************************************************/
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>
36 /// This class is a "mixin" and contains the common set of functions for several
37 /// distinct row-like classes.
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:
42 /// table[i].get_int(j) == table.get_int(i,j)
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.
50 /// When a row accessor is evaluated in a boolean context, it evaluates to true
51 /// if, and only if it is attached.
53 /// \tparam T A const or non-const table type (currently either `Table` or
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.
62 template <class T, class R>
67 typedef BasicTableRef<const T> ConstTableRef;
68 typedef BasicTableRef<T> TableRef; // Same as ConstTableRef if `T` is 'const'
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'
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;
96 U get(size_t col_ndx) const noexcept;
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);
117 template <typename U>
118 void set(size_t col_ndx, U&& value, bool is_default = false);
120 template <typename U>
121 void set_unique(size_t col_ndx, U&& value);
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);
127 /// Note that these operations will cause the row accessor to be detached.
129 void move_last_over();
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;
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;
141 /// Returns true if, and only if this accessor is currently attached to a
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
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;
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;
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;
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;
173 explicit operator bool() const noexcept;
176 const T* table() const noexcept;
178 size_t row_ndx() const noexcept;
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
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.
195 class BasicRowExpr : public RowFuncs<T, BasicRowExpr<T>> {
197 BasicRowExpr() noexcept = default;
200 BasicRowExpr(const BasicRowExpr<U>&) noexcept;
203 BasicRowExpr(const BasicRow<U>&) noexcept;
206 T* m_table = nullptr; // nullptr if detached.
207 size_t m_row_ndx = 0; // Undefined if detached.
209 BasicRowExpr(T*, size_t init_row_ndx) noexcept;
211 T* impl_get_table() const noexcept;
212 size_t impl_get_row_ndx() const noexcept;
213 void impl_detach() noexcept;
215 // Make impl_get_table(), impl_get_row_ndx(), and impl_detach() accessible
217 friend class RowFuncs<T, BasicRowExpr<T>>;
219 // Make m_table and m_row_ndx accessible from BasicRowExpr(const
220 // BasicRowExpr<U>&) for any U.
222 friend class BasicRowExpr;
224 // Make m_table and m_row_ndx accessible from
225 // BasicRow::BaicRow(BasicRowExpr<U>) for any U.
227 friend class BasicRow;
229 // Make BasicRowExpr(T*, size_t) accessible from Table.
238 TableRef m_table; // nullptr if detached.
239 size_t m_row_ndx; // Undefined if detached.
241 void attach(Table*, size_t row_ndx) noexcept;
242 void reattach(Table*, size_t row_ndx) noexcept;
243 void impl_detach() noexcept;
249 RowBase(const RowBase&) = delete;
250 using HandoverPatch = RowBaseHandoverPatch;
252 RowBase(const RowBase& source, HandoverPatch& patch);
255 static void generate_patch(const RowBase& source, HandoverPatch& patch);
256 void apply_patch(HandoverPatch& patch, Group& group);
259 RowBase* m_prev = nullptr; // nullptr if first, undefined if detached.
260 RowBase* m_next = nullptr; // nullptr if last, undefined if detached.
262 // Table needs to be able to modify m_table and m_row_ndx.
267 /// An accessor class for table rows (a.k.a. a "row accessor").
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.
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().
282 /// Row accessors are created and used as follows:
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();
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
292 /// Table* t = row.get_table(); // The parent table
293 /// size_t i = row.get_index(); // The current row index
297 class BasicRow : private RowBase, public RowFuncs<T, BasicRow<T>> {
302 BasicRow(BasicRowExpr<U>) noexcept;
304 BasicRow(const BasicRow<T>&) noexcept;
307 BasicRow(const BasicRow<U>&) noexcept;
310 BasicRow& operator=(BasicRowExpr<U>) noexcept;
313 BasicRow& operator=(BasicRow<U>) noexcept;
315 BasicRow& operator=(const BasicRow<T>&) noexcept;
317 ~BasicRow() noexcept;
320 T* impl_get_table() const noexcept;
321 size_t impl_get_row_ndx() const noexcept;
323 // Make impl_get_table(), impl_get_row_ndx(), and impl_detach() accessible
325 friend class RowFuncs<T, BasicRow<T>>;
327 // Make m_table and m_row_ndx accessible from BasicRow(const BasicRow<U>&)
330 friend class BasicRow;
332 // Make m_table and m_row_ndx accessible from BasicRowExpr(const
333 // BasicRow<U>&) for any U.
335 friend class BasicRowExpr;
338 std::unique_ptr<BasicRow<T>> clone_for_handover(std::unique_ptr<HandoverPatch>& patch) const
340 patch.reset(new HandoverPatch);
341 std::unique_ptr<BasicRow<T>> retval(new BasicRow<T>(*this, *patch));
345 static void generate_patch(const BasicRow& row, std::unique_ptr<HandoverPatch>& patch)
347 patch.reset(new HandoverPatch);
348 RowBase::generate_patch(row, *patch);
351 void apply_and_consume_patch(std::unique_ptr<HandoverPatch>& patch, Group& group)
353 apply_patch(*patch, group);
357 void apply_patch(HandoverPatch& patch, Group& group)
359 RowBase::apply_patch(patch, group);
363 BasicRow(const BasicRow<T>& source, HandoverPatch& patch)
364 : RowBase(source, patch)
367 friend class SharedGroup;
370 typedef BasicRow<Table> Row;
371 typedef BasicRow<const Table> ConstRow;
376 template <class T, class R>
377 inline int_fast64_t RowFuncs<T, R>::get_int(size_t col_ndx) const noexcept
379 return table()->get_int(col_ndx, row_ndx());
382 template <class T, class R>
383 inline bool RowFuncs<T, R>::get_bool(size_t col_ndx) const noexcept
385 return table()->get_bool(col_ndx, row_ndx());
388 template <class T, class R>
389 inline float RowFuncs<T, R>::get_float(size_t col_ndx) const noexcept
391 return table()->get_float(col_ndx, row_ndx());
394 template <class T, class R>
395 inline double RowFuncs<T, R>::get_double(size_t col_ndx) const noexcept
397 return table()->get_double(col_ndx, row_ndx());
400 template <class T, class R>
401 inline StringData RowFuncs<T, R>::get_string(size_t col_ndx) const noexcept
403 return table()->get_string(col_ndx, row_ndx());
406 template <class T, class R>
407 inline BinaryData RowFuncs<T, R>::get_binary(size_t col_ndx) const noexcept
409 return table()->get_binary(col_ndx, row_ndx());
412 template <class T, class R>
413 inline OldDateTime RowFuncs<T, R>::get_olddatetime(size_t col_ndx) const noexcept
415 return table()->get_olddatetime(col_ndx, row_ndx());
418 template <class T, class R>
419 inline Timestamp RowFuncs<T, R>::get_timestamp(size_t col_ndx) const noexcept
421 return table()->get_timestamp(col_ndx, row_ndx());
424 template <class T, class R>
425 inline typename RowFuncs<T, R>::ConstTableRef RowFuncs<T, R>::get_subtable(size_t col_ndx) const
427 return table()->get_subtable(col_ndx, row_ndx()); // Throws
430 template <class T, class R>
431 inline typename RowFuncs<T, R>::TableRef RowFuncs<T, R>::get_subtable(size_t col_ndx)
433 return table()->get_subtable(col_ndx, row_ndx()); // Throws
436 template <class T, class R>
437 inline size_t RowFuncs<T, R>::get_subtable_size(size_t col_ndx) const noexcept
439 return table()->get_subtable_size(col_ndx, row_ndx());
442 template <class T, class R>
443 inline size_t RowFuncs<T, R>::get_link(size_t col_ndx) const noexcept
445 return table()->get_link(col_ndx, row_ndx());
448 template <class T, class R>
449 inline bool RowFuncs<T, R>::is_null_link(size_t col_ndx) const noexcept
451 return table()->is_null_link(col_ndx, row_ndx());
454 template <class T, class R>
455 inline bool RowFuncs<T, R>::is_null(size_t col_ndx) const noexcept
457 return table()->is_null(col_ndx, row_ndx());
460 template <class T, class R>
461 inline typename RowFuncs<T, R>::ConstLinkViewRef RowFuncs<T, R>::get_linklist(size_t col_ndx) const
463 return table()->get_linklist(col_ndx, row_ndx()); // Throws
466 template <class T, class R>
467 inline typename RowFuncs<T, R>::LinkViewRef RowFuncs<T, R>::get_linklist(size_t col_ndx)
469 return table()->get_linklist(col_ndx, row_ndx()); // Throws
472 template <class T, class R>
473 inline bool RowFuncs<T, R>::linklist_is_empty(size_t col_ndx) const noexcept
475 return table()->linklist_is_empty(col_ndx, row_ndx());
478 template <class T, class R>
479 inline size_t RowFuncs<T, R>::get_link_count(size_t col_ndx) const noexcept
481 return table()->get_link_count(col_ndx, row_ndx());
484 template <class T, class R>
485 inline Mixed RowFuncs<T, R>::get_mixed(size_t col_ndx) const noexcept
487 return table()->get_mixed(col_ndx, row_ndx());
490 template <class T, class R>
491 inline DataType RowFuncs<T, R>::get_mixed_type(size_t col_ndx) const noexcept
493 return table()->get_mixed_type(col_ndx, row_ndx());
496 template <class T, class R>
498 inline U RowFuncs<T, R>::get(size_t col_ndx) const noexcept
500 return table()->template get<U>(col_ndx, row_ndx());
503 template <class T, class R>
504 inline void RowFuncs<T, R>::set_int(size_t col_ndx, int_fast64_t value)
506 table()->set_int(col_ndx, row_ndx(), value); // Throws
509 template <class T, class R>
510 inline void RowFuncs<T, R>::set_int_unique(size_t col_ndx, int_fast64_t value)
512 table()->set_int_unique(col_ndx, row_ndx(), value); // Throws
515 template <class T, class R>
516 inline void RowFuncs<T, R>::add_int(size_t col_ndx, int_fast64_t value)
518 table()->add_int(col_ndx, row_ndx(), value); // Throws
521 template <class T, class R>
522 inline void RowFuncs<T, R>::set_bool(size_t col_ndx, bool value)
524 table()->set_bool(col_ndx, row_ndx(), value); // Throws
527 template <class T, class R>
528 inline void RowFuncs<T, R>::set_float(size_t col_ndx, float value)
530 table()->set_float(col_ndx, row_ndx(), value); // Throws
533 template <class T, class R>
534 inline void RowFuncs<T, R>::set_double(size_t col_ndx, double value)
536 table()->set_double(col_ndx, row_ndx(), value); // Throws
539 template <class T, class R>
540 inline void RowFuncs<T, R>::set_string(size_t col_ndx, StringData value)
542 table()->set_string(col_ndx, row_ndx(), value); // Throws
545 template <class T, class R>
546 inline void RowFuncs<T, R>::set_string_unique(size_t col_ndx, StringData value)
548 table()->set_string_unique(col_ndx, row_ndx(), value); // Throws
551 template <class T, class R>
552 inline void RowFuncs<T, R>::set_binary(size_t col_ndx, BinaryData value)
554 table()->set_binary(col_ndx, row_ndx(), value); // Throws
557 template <class T, class R>
558 inline void RowFuncs<T, R>::set_olddatetime(size_t col_ndx, OldDateTime value)
560 table()->set_olddatetime(col_ndx, row_ndx(), value); // Throws
563 template <class T, class R>
564 inline void RowFuncs<T, R>::set_timestamp(size_t col_ndx, Timestamp value)
566 table()->set_timestamp(col_ndx, row_ndx(), value); // Throws
569 template <class T, class R>
570 inline void RowFuncs<T, R>::set_subtable(size_t col_ndx, const Table* value)
572 table()->set_subtable(col_ndx, row_ndx(), value); // Throws
575 template <class T, class R>
576 inline void RowFuncs<T, R>::set_link(size_t col_ndx, size_t value)
578 table()->set_link(col_ndx, row_ndx(), value); // Throws
581 template <class T, class R>
582 inline void RowFuncs<T, R>::nullify_link(size_t col_ndx)
584 table()->nullify_link(col_ndx, row_ndx()); // Throws
587 template <class T, class R>
588 inline void RowFuncs<T, R>::set_mixed(size_t col_ndx, Mixed value)
590 table()->set_mixed(col_ndx, row_ndx(), value); // Throws
593 template <class T, class R>
594 inline void RowFuncs<T, R>::set_mixed_subtable(size_t col_ndx, const Table* value)
596 table()->set_mixed_subtable(col_ndx, row_ndx(), value); // Throws
599 template <class T, class R>
600 inline void RowFuncs<T, R>::set_null(size_t col_ndx)
602 table()->set_null(col_ndx, row_ndx()); // Throws
605 template <class T, class R>
606 inline void RowFuncs<T, R>::set_null_unique(size_t col_ndx)
608 table()->set_null_unique(col_ndx, row_ndx()); // Throws
611 template <class T, class R>
613 inline void RowFuncs<T, R>::set(size_t col_ndx, U&& value, bool is_default)
615 table()->set(col_ndx, row_ndx(), std::forward<U>(value), is_default); // Throws
618 template <class T, class R>
620 inline void RowFuncs<T, R>::set_unique(size_t col_ndx, U&& value)
622 table()->set_unique(col_ndx, row_ndx(), std::forward<U>(value)); // Throws
625 template <class T, class R>
626 inline void RowFuncs<T, R>::insert_substring(size_t col_ndx, size_t pos, StringData value)
628 table()->insert_substring(col_ndx, row_ndx(), pos, value); // Throws
631 template <class T, class R>
632 inline void RowFuncs<T, R>::remove_substring(size_t col_ndx, size_t pos, size_t size)
634 table()->remove_substring(col_ndx, row_ndx(), pos, size); // Throws
637 template <class T, class R>
638 inline void RowFuncs<T, R>::remove()
640 table()->remove(row_ndx()); // Throws
643 template <class T, class R>
644 inline void RowFuncs<T, R>::move_last_over()
646 table()->move_last_over(row_ndx()); // Throws
649 template <class T, class R>
650 inline size_t RowFuncs<T, R>::get_backlink_count() const noexcept
652 return table()->get_backlink_count(row_ndx());
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
658 return table()->get_backlink_count(row_ndx(), src_table, src_col_ndx);
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
665 return table()->get_backlink(row_ndx(), src_table, src_col_ndx, backlink_ndx);
668 template <class T, class R>
669 inline size_t RowFuncs<T, R>::get_column_count() const noexcept
671 return table()->get_column_count();
674 template <class T, class R>
675 inline DataType RowFuncs<T, R>::get_column_type(size_t col_ndx) const noexcept
677 return table()->get_column_type(col_ndx);
680 template <class T, class R>
681 inline StringData RowFuncs<T, R>::get_column_name(size_t col_ndx) const noexcept
683 return table()->get_column_name(col_ndx);
686 template <class T, class R>
687 inline size_t RowFuncs<T, R>::get_column_index(StringData name) const noexcept
689 return table()->get_column_index(name);
692 template <class T, class R>
693 inline bool RowFuncs<T, R>::is_attached() const noexcept
695 return static_cast<const R*>(this)->impl_get_table();
698 template <class T, class R>
699 inline void RowFuncs<T, R>::detach() noexcept
701 static_cast<R*>(this)->impl_detach();
704 template <class T, class R>
705 inline const T* RowFuncs<T, R>::get_table() const noexcept
710 template <class T, class R>
711 inline T* RowFuncs<T, R>::get_table() noexcept
716 template <class T, class R>
717 inline size_t RowFuncs<T, R>::get_index() const noexcept
722 template <class T, class R>
723 inline RowFuncs<T, R>::operator bool() const noexcept
725 return is_attached();
728 template <class T, class R>
729 inline const T* RowFuncs<T, R>::table() const noexcept
731 return static_cast<const R*>(this)->impl_get_table();
734 template <class T, class R>
735 inline T* RowFuncs<T, R>::table() noexcept
737 return static_cast<R*>(this)->impl_get_table();
740 template <class T, class R>
741 inline size_t RowFuncs<T, R>::row_ndx() const noexcept
743 return static_cast<const R*>(this)->impl_get_row_ndx();
749 inline BasicRowExpr<T>::BasicRowExpr(const BasicRowExpr<U>& expr) noexcept
750 : m_table(expr.m_table)
751 , m_row_ndx(expr.m_row_ndx)
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)
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)
771 inline T* BasicRowExpr<T>::impl_get_table() const noexcept
777 inline size_t BasicRowExpr<T>::impl_get_row_ndx() const noexcept
783 inline void BasicRowExpr<T>::impl_detach() noexcept
790 inline BasicRow<T>::BasicRow() noexcept
795 inline BasicRow<T>::BasicRow(const BasicRow<T>& row) noexcept
798 attach(const_cast<Table*>(row.m_table.get()), row.m_row_ndx);
803 inline BasicRow<T>::BasicRow(BasicRowExpr<U> expr) noexcept
805 T* expr_table = expr.m_table; // Check that pointer types are compatible
806 attach(const_cast<Table*>(expr_table), expr.m_row_ndx);
811 inline BasicRow<T>::BasicRow(const BasicRow<U>& row) noexcept
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);
819 inline BasicRow<T>& BasicRow<T>::operator=(BasicRowExpr<U> expr) noexcept
821 T* expr_table = expr.m_table; // Check that pointer types are compatible
822 reattach(const_cast<Table*>(expr_table), expr.m_row_ndx);
828 inline BasicRow<T>& BasicRow<T>::operator=(BasicRow<U> row) noexcept
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);
836 inline BasicRow<T>& BasicRow<T>::operator=(const BasicRow<T>& row) noexcept
838 reattach(const_cast<Table*>(row.m_table.get()), row.m_row_ndx);
843 inline BasicRow<T>::~BasicRow() noexcept
845 RowBase::impl_detach();
849 inline T* BasicRow<T>::impl_get_table() const noexcept
851 return m_table.get();
855 inline size_t BasicRow<T>::impl_get_row_ndx() const noexcept
862 #endif // REALM_ROW_HPP