morganstanley/binlog

Recursive BINLOG_ADAPT_STRUCT for derived classes

Closed this issue · 6 comments

Hi,

Is there a recursive way to setup logging of derived classes that doesn't require having to repeatedly call the base class members/getters? Repeating base class members/getters in multiple derived classes can get quite cumbersome and results in lots of changes and easy to make errors if the base class is modified, e.g.,

BINLOG_ADAPT_STRUCT(Base, a, b)
BINLOG_ADAPT_STRUCT(Derived, c, d, Base)

instead of

BINLOG_ADAPT_STRUCT(Base, a, b)
BINLOAD_ADAPT_STRUCT(Dervied, c, d, a, b)

for

struct Base
{
   int a, b;
};
struct Derived : public Base
{
   int c,d;
};

Good question. My first thought: is adding a base getter an option?

struct Base
{
   int a, b;
};
struct Derived : public Base
{
   int c,d;
   const Base& base() const;
};
BINLOG_ADAPT_STRUCT(Derived, base, c, d)

Good question. My first thought: is adding a base getter an option?

I think your suggestion will work well. It will, of course, require people to make a modification to their classes rather than just calling an external macro (from potentially any location in their code base). Longer term it might be an idea to support something similar from within the BINLOG_ADAPT_STRUCT call that doesn't require the user to make additions to their classes. Perhaps a helper macro SERIALIZE_AS(Base) which could be implemented by statically casting the type to the provided argument?

BINLOG_ADAPT_STRUCT(Derived, SERIALIZE_AS(Base), c, d)

This alternative might be easier to implement:

BINLOG_ADAPT_DERIVED_STRUCT(Derived, Base, c, d)

Of course, this only works for public inheritance. How would the desired output look like?

Derived { a: 0, b: 1, c: 2, d: 3 }

or

Derived { Base { a: 0, b: 1 }, c: 2, d: 3 }

Derived { Base { a: 0, b: 1 }, c: 2, d: 3 }

I think this would make the most sense.

A problem I foresee with your design is it won't support multiple inheritance.

BINLOG_ADAPT_DERIVED_STRUCT(Derived, (Base), c, d)
BINLOG_ADAPT_DERIVED_STRUCT(Derived, (Base1, Base2), c, d)

This one could support multiple inheritance (however, I didn't try any of these), but not templates. I fear that with templates it gets really complicated.

FYI, #130 will fix this, if I manage to make it work on MSVC some time later.