
Hi Everyone, Some feedback from playing with Boost.Describe for class types. 1. As others pointed out, it is confusing that BOOST_DESCRIBE_STRUCT() and BOOST_DESCRIBE_CLASS() have such close names, but their interface and requirements are so different. Maybe rename the latter to BOOST_DESCRIBE_THIS_CLASS()? 2. Base class subobjects are in some applications treated equivalently to member subobject; this is why I found it surprising that I cannot get the names of base class subobjects. But I guess there are implementation difficulties. Bases can be qualified names. 3. As with enums, _public_member_descriptor_fn in global namespace is UB or invalid program as per http://eel.is/c++draft/lex.name#3.2. 4. As others pointed out, the part of the interface that uses enum modifiers is not intuitive. I think that after a while it starts to make sense: you decide on your use case (like doing RPC), form your enum bitmask, and then pass it everywhere. It became more-less clear to me only after I had a look at the implementation of member_filter: https://github.com/pdimov/describe/blob/develop/include/boost/describe/membe... Maybe it makes sense to expose this in the docs. 5. Modifier mod_inherited is great for flattening the inheritance structure: struct X { int a; }; struct Y : X { int b; }; struct Z : Y { int c; }; BOOST_DESCRIBE_STRUCT(X, (), (a)); BOOST_DESCRIBE_STRUCT(Y, (X), (b)); BOOST_DESCRIBE_STRUCT(Z, (Y), (c)); int main() { namespace desc = boost::describe; using namespace std::literals::string_literals; constexpr auto mod = static_cast<desc::modifiers>(desc::mod_public | desc::mod_inherited); using L = desc::describe_members<Z, mod>; assert((boost::mp11::mp_at_c<L, 0>::name == "a"s)); assert((boost::mp11::mp_at_c<L, 1>::name == "b"s)); assert((boost::mp11::mp_at_c<L, 2>::name == "c"s)); } But it is not obvious at first. I recommend that the docs provide an example like this. It even works when base classes have members with same names: struct X { int a; }; struct Y { int a; }; struct Z : X, Y { int b; }; BOOST_DESCRIBE_STRUCT(X, (), (a)); BOOST_DESCRIBE_STRUCT(Y, (), (a)); BOOST_DESCRIBE_STRUCT(Z, (X, Y), (b)); int main() { constexpr auto mod = static_cast<describe::modifiers>(describe::mod_public | describe::mod_inherited); using L = describe::describe_members<Z, mod>; Z z = {{{3}}, {{6}}, {9}}; assert((z.*mp_at_c<L, 0>::pointer == 3)); assert((z.*mp_at_c<L, 1>::pointer == 6)); assert((z.*mp_at_c<L, 2>::pointer == 9)); } 5. What is the use case for modifier mod_hidden? I cannot think of any situation where I would need it. 6. Regarding the overloaded functions, I am no expert in preprocessor metaprogramming, but maybe if there was a way to provide function signatures along the name, you would have enough information to form the pointers. Something like: struct X { void f(int){} void f(void*){} }; BOOST_DESCRIBE_STRUCT(X, (), ( SIGNATURE(void f(int)), SIGNATURE(void f(void*)) ); 7. Modifier mod_virtual works unintuitively. It does not affect the filtering in describe_bases<>. It is only used for decorating the list elements. Maybe the docs should be more explicit about what it is used for. Again, is there a use case for this? Regards, &rzej;