boost::pfr 有自定义成员

boost::pfr with customized member

我正在尝试使用 boost::pfr 进行基本反射,但当其中一个成员是自定义类型(如 class 或结构)时编译失败,这是为什么?修复的方法是什么?我正在使用 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';

使用现代 C++ 构建反射系统非常容易。这是我自己的库中的示例(C++20 和一个 WIP)。 注意:这个库的设计在很大程度上受 boost fusion 的影响,如果你想在一个可移植的 C++ 库中复杂化一些东西,你可以考虑使用它

#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);
};

https://github.com/Tiger4Hire2/NetworkingExamples

您需要为 S1 提供 operator<<,因为 boost::pfr::io 依赖现有的:

std::ostream& operator<<(std::ostream& os, const S1& x)
{
    return os << boost::pfr::io_fields(x);
}

live example on godbolt.org