Skip to content

Commit 0a8054e

Browse files
committed
Merge #12731: Support serialization as another type without casting
818dc74 Support serialization as another type without casting (Pieter Wuille) Pull request description: This adds a `READWRITEAS(type, obj)` macro which serializes `obj` as if it were converted to `const type&` when `const`, and to `type&` when non-`const`. No actual cast is involved, so this only works when this conversion can be done automatically. 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. This is a redo of #12712, using a slightly different interface. Tree-SHA512: 262f0257284ff99b5ffaec9b997c194e221522ba35c3ac8eaa9bb344449d7ea0a314de254dc77449fa7aaa600f8cd9a24da65aade8c1ec6aa80c6e9a7bba5ca7
2 parents a84b056 + 818dc74 commit 0a8054e

File tree

7 files changed

+13
-8
lines changed

7 files changed

+13
-8
lines changed

src/addrman.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class CAddrInfo : public CAddress
5959

6060
template <typename Stream, typename Operation>
6161
inline void SerializationOp(Stream& s, Operation ser_action) {
62-
READWRITE(*static_cast<CAddress*>(this));
62+
READWRITEAS(CAddress, *this);
6363
READWRITE(source);
6464
READWRITE(nLastSuccess);
6565
READWRITE(nAttempts);

src/primitives/block.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class CBlock : public CBlockHeader
9393

9494
template <typename Stream, typename Operation>
9595
inline void SerializationOp(Stream& s, Operation ser_action) {
96-
READWRITE(*static_cast<CBlockHeader*>(this));
96+
READWRITEAS(CBlockHeader, *this);
9797
READWRITE(vtx);
9898
}
9999

src/protocol.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ class CAddress : public CService
349349
uint64_t nServicesInt = nServices;
350350
READWRITE(nServicesInt);
351351
nServices = static_cast<ServiceFlags>(nServicesInt);
352-
READWRITE(*static_cast<CService*>(this));
352+
READWRITEAS(CService, *this);
353353
}
354354

355355
// TODO: make private (improves encapsulation)

src/script/script.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ class CScript : public CScriptBase
415415

416416
template <typename Stream, typename Operation>
417417
inline void SerializationOp(Stream& s, Operation ser_action) {
418-
READWRITE(static_cast<CScriptBase&>(*this));
418+
READWRITEAS(CScriptBase, *this);
419419
}
420420

421421
CScript& operator+=(const CScript& b)

src/serialize.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,12 @@ enum
155155
SER_GETHASH = (1 << 2),
156156
};
157157

158-
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
158+
//! Convert the reference base type to X, without changing constness or reference type.
159+
template<typename X> X& ReadWriteAsHelper(X& x) { return x; }
160+
template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
161+
162+
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
163+
#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
159164

160165
/**
161166
* Implement three methods for serializable objects. These are actually wrappers over

src/txdb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct CDiskTxPos : public CDiskBlockPos
4747

4848
template <typename Stream, typename Operation>
4949
inline void SerializationOp(Stream& s, Operation ser_action) {
50-
READWRITE(*static_cast<CDiskBlockPos*>(this));
50+
READWRITEAS(CDiskBlockPos, *this);
5151
READWRITE(VARINT(nTxOffset));
5252
}
5353

src/wallet/wallet.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ class CWalletTx : public CMerkleTx
396396
mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
397397
}
398398

399-
s << *static_cast<const CMerkleTx*>(this);
399+
s << static_cast<const CMerkleTx&>(*this);
400400
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
401401
s << vUnused << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << fSpent;
402402
}
@@ -407,7 +407,7 @@ class CWalletTx : public CMerkleTx
407407
Init(nullptr);
408408
char fSpent;
409409

410-
s >> *static_cast<CMerkleTx*>(this);
410+
s >> static_cast<CMerkleTx&>(*this);
411411
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
412412
s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent;
413413

0 commit comments

Comments
 (0)