dbg-macro icon indicating copy to clipboard operation
dbg-macro copied to clipboard

Add support for simple structs?

Open sharkdp opened this issue 5 years ago • 8 comments

It would be cool to somehow add support for simple structs/classes like

struct CustomDatatype {
  int field1;
  std::string field2;
};

// …

CustomDatatype c{42, "hello"};
dbg(c);

We would somehow have to iterate over all members... without modifying to original struct definition. Not sure if this is possible in C++ (without reflection).

sharkdp avatar Jun 19 '19 21:06 sharkdp

You can use magic_get (https://www.youtube.com/watch?v=abdeAew3gmQ). Requires C++14.

hmenke avatar Jun 20 '19 06:06 hmenke

magic_get looks fantastic, thank you for the reference.

If there is a small subset of the code that we could include in dbg.h (assuming there are no licensing problems, see similar discussion in #4 and #5), I think that would be a great addition. It looks like there is no way to get the actual name of the fields, so the best we could do would probably be an output like:

dbg(c); // CustomDatatype{42, "hello"}

(which would already be great).

sharkdp avatar Jun 20 '19 17:06 sharkdp

There's also cista, which uses another approach for simple type reflection (see to_tuple.h for example).

AlexBAV avatar Jun 20 '19 19:06 AlexBAV

There's also cista, which uses another approach for simple type reflection (see to_tuple.h for example).

Thank you for the reference! Unfortunately, it seems to rely on C++17 functionality, but I would really like dbg(…) to be C++11 compatible.

sharkdp avatar Jun 20 '19 20:06 sharkdp

Would it be good enough if magic_get-derived functionality was under #ifdef __cplusplus, so people using C++14 or later get it automatically and those limited to C++11 define showValue as usual?

For C++11, I think it's possible to define a macro so SHOW(CustomDatatype, field1, field2) expands to

inline bool pretty_print(std::ostream& stream, const CustomDatatype& value) {
  stream << "CustomDatatype" "{" "field1" ": " << value.field1 << ", " "field2" ": " << value.field2 << "}";
  return true;
}

based on this technique but it's tricky.

alexeyr avatar Apr 05 '21 12:04 alexeyr

Agreed. If the concerns above (license, code size) can be clarified, I'd be willing to accept this addition.

sharkdp avatar Apr 13 '21 13:04 sharkdp

@sharkdp Here is a proposal to incorporate this feature. This is a working example that I came up with based on the above discussions and some snippets from here.

Sample driver code

struct MetaData {
    std::string name;
    int64_t id;
};

struct Entity3D {
    int32_t x, y, z;
    MetaData meta;
};

DBG_REGISTER_STRUCT(MetaData, name, id)
DBG_REGISTER_STRUCT(Entity3D, x, y, z, meta)

int32_t main() {
    Entity3D e = {3, 2, 1, {"dummy_name", 98765}};
    dbg(e);  // [main.cc:34 (main)] e = {'x': 3, 'y': 2, 'z': 1, 'meta': {'name': "dummy_name", 'id': 98765}} (Entity3D)
}

If this is satisfactory I'll be glad to open a PR!

winwinashwin avatar Jan 18 '23 09:01 winwinashwin

Thank you. If we add support for this, then I would definitely look for a solution which does not require any additional macro calls like DBG_REGISTER_STRUCT.

sharkdp avatar Feb 28 '23 20:02 sharkdp