This answer, explains what are SERIALIZE_METHODS and DESERIALIZE_METHODS macros in the Bitcoin Core. They prevent duplicate code for implementing the serialization and deserialization logic. But I've seen some classes in the Bitcoin Core which do the serialization differently. Here's an example:
/**
* A UTXO entry.
*
* Serialized format:
* - VARINT((coinbase ? 1 : 0) | (height << 1))
* - the non-spent CTxOut (via TxOutCompression)
*/
class Coin
{
...
template<typename Stream>
void Serialize(Stream &s) const {
assert(!IsSpent());
uint32_t code = nHeight * uint32_t{2} + fCoinBase;
::Serialize(s, VARINT(code));
::Serialize(s, Using<TxOutCompression>(out));
}
template<typename Stream>
void Unserialize(Stream &s) {
uint32_t code = 0;
::Unserialize(s, VARINT(code));
nHeight = code >> 1;
fCoinBase = code & 1;
::Unserialize(s, Using<TxOutCompression>(out));
}
So, what's the difference between these two way of implementing serializing and deserializing methods?