aboutsummaryrefslogtreecommitdiff
path: root/src/serialize.h
diff options
context:
space:
mode:
authorMarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>2020-07-11 09:55:38 +0200
committerMarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>2023-08-28 17:48:15 +0200
commitaaaa3fa9477eef9ea72e4a501d130c57b47b470a (patch)
tree5cb4db76123a10ff6ff2c24d1278a584eca04d40 /src/serialize.h
parent1c1a02bbd246101fd477b0897aef971b511b4241 (diff)
Replace READWRITEAS macro with AsBase wrapping function
Co-authored-by: Pieter Wuille <pieter@wuille.net>
Diffstat (limited to 'src/serialize.h')
-rw-r--r--src/serialize.h36
1 files changed, 32 insertions, 4 deletions
diff --git a/src/serialize.h b/src/serialize.h
index 39f2c0f3ae..08c10fbce4 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -133,12 +133,40 @@ enum
SER_GETHASH = (1 << 2),
};
-//! Convert the reference base type to X, without changing constness or reference type.
-template<typename X> X& ReadWriteAsHelper(X& x) { return x; }
-template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
+/**
+ * Convert any argument to a reference to X, maintaining constness.
+ *
+ * This can be used in serialization code to invoke a base class's
+ * serialization routines.
+ *
+ * Example use:
+ * class Base { ... };
+ * class Child : public Base {
+ * int m_data;
+ * public:
+ * SERIALIZE_METHODS(Child, obj) {
+ * READWRITE(AsBase<Base>(obj), obj.m_data);
+ * }
+ * };
+ *
+ * static_cast cannot easily be used here, as the type of Obj will be const Child&
+ * during serialization and Child& during deserialization. AsBase will convert to
+ * const Base& and Base& appropriately.
+ */
+template <class Out, class In>
+Out& AsBase(In& x)
+{
+ static_assert(std::is_base_of_v<Out, In>);
+ return x;
+}
+template <class Out, class In>
+const Out& AsBase(const In& x)
+{
+ static_assert(std::is_base_of_v<Out, In>);
+ return x;
+}
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
-#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })