aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2017-07-07 16:06:56 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2018-03-20 17:08:06 -0700
commit818dc74ba2745872fd68d2158380fc8bd331210e (patch)
treef72178344d09e88a312da73abed27f1716b8cfdd
parent8ee5c7b747171e335793c74cd9d2f7491da58164 (diff)
downloadbitcoin-818dc74ba2745872fd68d2158380fc8bd331210e.tar.xz
Support serialization as another type without casting
This adds a READWRITEAS(type, obj) macro which serializes obj as if it were casted to (const type&) when const, and to (type&) when non-const. This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved.
-rw-r--r--src/addrman.h2
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/protocol.h2
-rw-r--r--src/script/script.h2
-rw-r--r--src/serialize.h7
-rw-r--r--src/txdb.h2
-rw-r--r--src/wallet/wallet.h4
7 files changed, 13 insertions, 8 deletions
diff --git a/src/addrman.h b/src/addrman.h
index 67423c6c55..3f163dab65 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -59,7 +59,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*static_cast<CAddress*>(this));
+ READWRITEAS(CAddress, *this);
READWRITE(source);
READWRITE(nLastSuccess);
READWRITE(nAttempts);
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 5d6d44ac76..1fca55d910 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -93,7 +93,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*static_cast<CBlockHeader*>(this));
+ READWRITEAS(CBlockHeader, *this);
READWRITE(vtx);
}
diff --git a/src/protocol.h b/src/protocol.h
index e518d11944..b8deacb5f4 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -349,7 +349,7 @@ public:
uint64_t nServicesInt = nServices;
READWRITE(nServicesInt);
nServices = static_cast<ServiceFlags>(nServicesInt);
- READWRITE(*static_cast<CService*>(this));
+ READWRITEAS(CService, *this);
}
// TODO: make private (improves encapsulation)
diff --git a/src/script/script.h b/src/script/script.h
index 591777672e..8e5a792c7d 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -415,7 +415,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(static_cast<CScriptBase&>(*this));
+ READWRITEAS(CScriptBase, *this);
}
CScript& operator+=(const CScript& b)
diff --git a/src/serialize.h b/src/serialize.h
index 91da6b0f80..341a138e8b 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -148,7 +148,12 @@ enum
SER_GETHASH = (1 << 2),
};
-#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
+//! 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; }
+
+#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
+#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
/**
* Implement three methods for serializable objects. These are actually wrappers over
diff --git a/src/txdb.h b/src/txdb.h
index 2fc69e563b..830b65a322 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -46,7 +46,7 @@ struct CDiskTxPos : public CDiskBlockPos
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
- READWRITE(*static_cast<CDiskBlockPos*>(this));
+ READWRITEAS(CDiskBlockPos, *this);
READWRITE(VARINT(nTxOffset));
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 5ac8457eb4..ae94d53401 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -395,7 +395,7 @@ public:
mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
}
- s << *static_cast<const CMerkleTx*>(this);
+ s << static_cast<const CMerkleTx&>(*this);
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
s << vUnused << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << fSpent;
}
@@ -406,7 +406,7 @@ public:
Init(nullptr);
char fSpent;
- s >> *static_cast<CMerkleTx*>(this);
+ s >> static_cast<CMerkleTx&>(*this);
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent;