I’m not sure it’s desirable, I know multiple inheritance can be a bit of a mess, and frankly I’m too unfamiliar with it to assess whether or not this is a better approach. Just thought I’d share since it does lead to a fair amount of code deduplication. Since it’s a transitory phase, I think it might make sense. Compiles and unit tests are fine:
0diff --git a/src/hash.h b/src/hash.h
1index b2ef29fcd..05d72dbab 100644
2--- a/src/hash.h
3+++ b/src/hash.h
4@@ -145,7 +145,7 @@ public:
5 }
6 };
7
8-class CHashWriter : public HashWriter
9+class CHashWriter : virtual public HashWriter
10 {
11 private:
12 const int nType;
13@@ -167,7 +167,7 @@ public:
14
15 /** Reads data from an underlying stream, while hashing the read data. */
16 template <typename Source>
17-class HashVerifier : public HashWriter
18+class HashVerifier : virtual public HashWriter
19 {
20 private:
21 Source& m_source;
22@@ -200,29 +200,10 @@ public:
23 };
24
25 template<typename Source>
26-class CHashVerifier : public CHashWriter
27+class CHashVerifier : public CHashWriter, public HashVerifier<Source>
28 {
29-private:
30- Source* source;
31-
32 public:
33- explicit CHashVerifier(Source* source_) : CHashWriter(source_->GetType(), source_->GetVersion()), source(source_) {}
34-
35- void read(Span<std::byte> dst)
36- {
37- source->read(dst);
38- this->write(dst);
39- }
40-
41- void ignore(size_t nSize)
42- {
43- std::byte data[1024];
44- while (nSize > 0) {
45- size_t now = std::min<size_t>(nSize, 1024);
46- read({data, now});
47- nSize -= now;
48- }
49- }
50+ explicit CHashVerifier(Source* source) : CHashWriter(source->GetType(), source->GetVersion()), HashVerifier<Source>(*source) {}
51
52 template<typename T>
53 CHashVerifier<Source>& operator>>(T&& obj)