In the documentation for boost describe, under the heading "Automatic Conversion to JSON", it shows how to implement "a universal tag_invoke overload that automatically converts an annotated struct to a Boost.JSON value". The example supports BOOST_DESCRIBE_STRUCT, how would I implement something similar for BOOST_DEFINE_ENUM_CLASS?
Here is my naive attempt to adapt the example to support BOOST_DEFINE_ENUM_CLASS alongside BOOST_DESCRIBE_STRUCT:
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <type_traits>
#include <vector>
#include <map>
namespace app {
template<class T,
class D1 = boost::describe::describe_members<T, boost::describe::mod_public | boost::describe::mod_protected>,
class D2 = boost::describe::describe_members<T, boost::describe::mod_private>,
class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value> >
void tag_invoke(boost::json::value_from_tag const&, boost::json::value& v, T const& t) {
auto& obj = v.emplace_object();
boost::mp11::mp_for_each<D1>([&](auto D) {
obj[D.name] = boost::json::value_from(t.*D.pointer);
});
}
struct A {
int x;
int y;
};
BOOST_DESCRIBE_STRUCT(A, (), (x, y))
struct B {
std::vector<A> v;
std::map<std::string, A> m;
};
BOOST_DESCRIBE_STRUCT(B, (), (v, m))
BOOST_DEFINE_ENUM_CLASS(E1, v1, v2, v3)
struct C {
int x;
E1 e1;
};
BOOST_DESCRIBE_STRUCT(C, (), (x, e1))
} // namespace app
#include <iostream>
void main() {
app::A a{ 1, 2 };
std::cout << boost::json::value_from(a) << std::endl;
app::B b{ { { 1, 2 }, { 3, 4 } }, { { "k1", { 5, 6 } }, { "k2", { 7, 8 } } } };
std::cout << boost::json::value_from(b) << std::endl;
app::C c{ 1, app::E1::v1 };
//std::cout << boost::json::value_from(c) << std::endl;
}
What do I need to do in order to enable boost::json::value_from() for c?
Edit: Okey dokes, the code below does the trick, but I got to make it more templatey:
void tag_invoke(boost::json::value_from_tag const&, boost::json::value& v, E1 const& t) {
v = boost::describe::enum_to_string(t, "x");
}
The documentation gives this example (slightly modified to suit our JSON needs later):
You can use that to implement the
value_from
customization point:Given suitable SFINAE you can template that on any enum type, as long as you keep in mind to limit the ADL applicability to your own enums to avoid interfering with other libraries.
Live demo:
Live On Compiler Explorer
Prints