@@ -133,12 +133,40 @@ enum
133133 SER_GETHASH = (1 << 2 ),
134134};
135135
136- // ! Convert the reference base type to X, without changing constness or reference type.
137- template <typename X> X& ReadWriteAsHelper (X& x) { return x; }
138- template <typename X> const X& ReadWriteAsHelper (const X& x) { return x; }
136+ /* *
137+ * Convert any argument to a reference to X, maintaining constness.
138+ *
139+ * This can be used in serialization code to invoke a base class's
140+ * serialization routines.
141+ *
142+ * Example use:
143+ * class Base { ... };
144+ * class Child : public Base {
145+ * int m_data;
146+ * public:
147+ * SERIALIZE_METHODS(Child, obj) {
148+ * READWRITE(AsBase<Base>(obj), obj.m_data);
149+ * }
150+ * };
151+ *
152+ * static_cast cannot easily be used here, as the type of Obj will be const Child&
153+ * during serialization and Child& during deserialization. AsBase will convert to
154+ * const Base& and Base& appropriately.
155+ */
156+ template <class Out , class In >
157+ Out& AsBase (In& x)
158+ {
159+ static_assert (std::is_base_of_v<Out, In>);
160+ return x;
161+ }
162+ template <class Out , class In >
163+ const Out& AsBase (const In& x)
164+ {
165+ static_assert (std::is_base_of_v<Out, In>);
166+ return x;
167+ }
139168
140169#define READWRITE (...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
141- #define READWRITEAS (type, obj ) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
142170#define SER_READ (obj, code ) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
143171#define SER_WRITE (obj, code ) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
144172
0 commit comments