Skip to content

Commit a6e5ddc

Browse files
committed
Support serialization as another type without casting
With the new AsType function it's possible to serialize an object as another (compatible) type, and is intended for invoking the serializer of a parent class. Writing AsType<Parent>(child) will work in any context: * READWRITE(AsType<Parent>(child)) * s << AsType<Parent>(child) * s >> AsType<Parent>(child) In case child is const, the result will be a reference to a const Parent type, resulting in const-correct behavior.
1 parent 585db41 commit a6e5ddc

File tree

7 files changed

+13
-7
lines changed

7 files changed

+13
-7
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+
READWRITE(AsType<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+
READWRITE(AsType<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+
READWRITE(AsType<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+
READWRITE(AsType<CScriptBase>(*this));
419419
}
420420

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

src/serialize.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ enum
150150

151151
#define READWRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
152152

153+
//! Convert the reference base type to X, without changing constness or reference type.
154+
template<typename X> X& AsType(X& x) { return x; }
155+
template<typename X> const X& AsType(const X& x) { return x; }
156+
template<typename X> X&& AsType(X&& x) { return std::move(x); }
157+
template<typename X> const X&& AsType(const X&& x) { return std::move(x); }
158+
153159
/**
154160
* Implement three methods for serializable objects. These are actually wrappers over
155161
* "SerializationOp" template, which implements the body of each class' serialization

src/txdb.h

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

4747
template <typename Stream, typename Operation>
4848
inline void SerializationOp(Stream& s, Operation ser_action) {
49-
READWRITE(*static_cast<CDiskBlockPos*>(this));
49+
READWRITE(AsType<CDiskBlockPos>(*this));
5050
READWRITE(VARINT(nTxOffset));
5151
}
5252

src/wallet/wallet.h

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

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

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

0 commit comments

Comments
 (0)