I'm trying to use boost::pfr for basic reflection, and it fails to compile when one of the member is customized type, like a class or struct, why is this? What's the way to fix it? I'm using C 17.
// this works:
struct S1 {
int n;
std::string name;
};
S1 o1{1, "foobar"};
std::cout << boost::pfr::io(o1) << '\n';
// but this does not work:
struct S2 {
int m;
S1 s1; // <===== this fields fails to compile
};
S2 o2;
std::cout << boost::pfr::io(o2) << '\n';
CodePudding user response:
You need to provide operator<< for S1, as boost::pfr::io relies on it existing:
std::ostream& operator<<(std::ostream& os, const S1& x)
{
return os << boost::pfr::io_fields(x);
}
CodePudding user response:
It is surprisingly easy to build a reflection system with modern C . Here is an example from my own library (C 20 and a WIP). NOTE: The design of this library is heavily influenced by boost fusion, which you might consider if you want to complex things in a portable C library
#include "Common/Reflection.h"
#include "Common/Json.h"
#include <utility>
#include <span>
#include <iostream>
#include <sstream>
struct Point
{
int x, y;
static constexpr auto get_members()
{
return std::make_tuple(
Member("x", &Point::x),
Member("y", &Point::y)
);
}
};
struct Line
{
Point from, to;
static constexpr auto get_members()
{
return std::make_tuple(
Member("from", &Line::from),
Member("to", &Line::to)
);
}
};
template<class T>
void ReverseEndian(T& v)
{
const auto as_bytes = std::as_writable_bytes(std::span(&v, 1));
std::reverse(as_bytes.begin(), as_bytes.end());
}
int main()
{
Line l{ {0x12345678, 0x12345678}, {0x12345678, 0x12345678} };
visit_recursive(l, [](auto& v) {ReverseEndian(v); });
JSON(std::cout, l);
std::cout << std::endl;
std::istringstream is("{\"from\"={\"x\"=1}, \"to\"={\"y\"=2}}");
JSON(is, l);
};
