是否有一种方法可以自动生成或至少缩短(例如__all__之类的参数)序列化函数?

问题描述 投票:0回答:1

我正在处理一个将消息(请求和响应)作为结构进行传输的网络。为了实现这一目标,我转向了增强串行化,效果很好!但是,由于消息和响应的类型如此之多,很难在所有这些消息和响应中都包含序列化功能,是否存在为所有结构自动生成方法或至少一次公开每个成员变量的捷径?

示例:

#pragma once

#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
struct Test
{
    public:
        int a;
        int b;
        template<typename archive> void serialize(archive& ar, const unsigned version) {
        ar & a; 
        ar & b;
    }
};
c++ boost automation boost-asio boost-serialization
1个回答
0
投票

我相信我已经回答了此yesterday

struct Test {
    int a,b;
    template<typename Ar> void serialize(Ar& ar, unsigned) { ar & a & b; }
};

请注意,如果您还序列化一个自由函数(使用ADL查找):

struct Test {
    int a,b;
};

template<typename Ar> void serialize(Ar& ar, Test& o, unsigned) {
    ar & o.a & o.b;
}

因此您可以单独获得序列化代码。最后,如果您有一组预定义的存档,则序列化功能根本不需要是模板:

using OArchive = boost::archive::binary_oarchive;
using IArchive = boost::archive::binary_iarchive;

struct Test {
    int a,b;
    void serialize(OArchive& ar, ...) const { ar & a & b; }
    void serialize(IArchive& ar, ...)       { ar & a & b; }
};

当然,这会产生一些重复。我很乐意忽略带有可变变量的version参数,但是在翻转大小上,它更const正确。

其他想法

如果您的结构是二进制可序列化的,则将它们标记为:

  • Boost serialization bitwise serializability
  • 或显式将它们视为blob:make_binary_object-在这种情况下,您不需要任何序列化方法:

    make_binary_object

    Live On Coliru

    打印

    #include <boost/archive/text_oarchive.hpp>
    #include <boost/serialization/binary_object.hpp>
    #include <iostream>
    using boost::serialization::make_binary_object;
    
    struct Test { int a,b; };
    
    int main() {
        boost::archive::text_oarchive oa(std::cout, boost::archive::no_header);
    
        Test req {13,31};
        oa << make_binary_object(&req, sizeof(req));
    }
    

对程序进行元编程

公平警告,作为C程序员,您可能想纾困,而在这里只使用更多的预处理器魔术/代码生成器

说您有更多消息(可以嵌套):

DQAAAB8AAAA=

您可以将其改编为namespace Messages { struct FooMsg { int a, b; }; struct BarMsg { std::string c; double d; }; struct QuxMsg { FooMsg e; BarMsg f; }; }

Fusion Sequences

好是现在您可以跨这些序列编写通用代码,所以让我们介绍我们自己的BOOST_FUSION_ADAPT_STRUCT(Messages::FooMsg, a, b) BOOST_FUSION_ADAPT_STRUCT(Messages::BarMsg, c, d) BOOST_FUSION_ADAPT_STRUCT(Messages::QuxMsg, e, f)

serialization wrapper

现在您可以对任何包装的消息实施序列化:

namespace Messages {
    template <typename T>
    struct MsgSerializationWrapper {
        T& ref;
    };

    template <typename T>
    static inline MsgSerializationWrapper<T> wrap(T& msg) { return {msg}; }

当然,我们需要一些检查来检测何时包装的类型不是融合序列,并以常规方式序列化该序列。

完整演示

template <typename Ar, typename Msg> void serialize(Ar& ar, MsgSerializationWrapper<Msg> wrapped, unsigned) { boost::fusion::for_each(wrapped.ref, [&ar](auto& field) { ar & wrap(field); }); }

Live On Coliru

打印

#include <boost/archive/text_oarchive.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>

namespace Messages {
    struct FooMsg { int a, b; };
    struct BarMsg { std::string c; double d; };
    struct QuxMsg { FooMsg e; BarMsg f; };
}

BOOST_FUSION_ADAPT_STRUCT(Messages::FooMsg, a, b)
BOOST_FUSION_ADAPT_STRUCT(Messages::BarMsg, c, d)
BOOST_FUSION_ADAPT_STRUCT(Messages::QuxMsg, e, f)

namespace Messages {
    template <typename T>
    struct MsgSerializationWrapper {
        T& ref;
    };

    template <typename T>
    static inline MsgSerializationWrapper<T> wrap(T& msg) { return {msg}; }

    template <typename Ar, typename Msg>
    std::enable_if_t<boost::fusion::traits::is_sequence<Msg>::value>
    serialize(Ar& ar, MsgSerializationWrapper<Msg> wrapped, unsigned) {
        boost::fusion::for_each(wrapped.ref, [&ar](auto& field) { ar & wrap(field); });
    }

    template <typename Ar, typename Primitive>
    std::enable_if_t<not boost::fusion::traits::is_sequence<Primitive>::value>
    serialize(Ar& ar, MsgSerializationWrapper<Primitive> wrapped, unsigned) {
        ar & wrapped.ref;
    }
}

int main() {
    boost::archive::text_oarchive oa(std::cout);

    Messages::QuxMsg req { 
        Messages::FooMsg { 42, 99 },
        Messages::BarMsg { "hello world\n", 3.14e100 },
    };

    oa << wrap(req);
}
© www.soinside.com 2019 - 2024. All rights reserved.