是否有一种(便携式)检测C+&#x2B中布局更改的方法。课程?

发布于 2025-01-30 10:50:31 字数 1387 浏览 3 评论 0原文

例如,说我有一个具有典型序列化模式的类foo。

struct Foo {
    int a;
    bool b;
    template <typename Archive>
    void serialize(Archive & ar) {
        ar & a;
        ar & b;
    }
};

现在假设有人来并增加了一个字段。

struct Foo {
    int a;
    bool b;
    std::string c;

    template <typename Archive>
    void serialize(Archive & ar) {
        ar & a;
        ar & b;
    }
};

这可以很好地编译,但是存档方法是错误的。我可以添加类似的东西


namespace detail {
template <int a, int b>
void AssertSizeOfImplementation() {
    static_assert(a == b, "Size does not match (check stack trace)");
}
}  
template <typename T, int size>
void AssertSizeOf() {
    detail::AssertSizeOfImplementation<sizeof(T), size>();
}


struct Foo {
    int a;
    bool b;

    template <typename Archive>
    void serialize(Archive& ar) {
        ar& a;
        ar& b;
        AssertSizeOf<Foo,8>();
    }
};

,现在如果添加额外的字段,我会看到一个编译错误

:在实例化'void细节:: sostSizeOfimplementation()[int a = 40; int b = 8]':

然后,我可以修复我的序列化代码并更新断言。

但是,这不是非常便携的。 sizeof 将根据包装和体系结构返回不同的结果。

使用SizeOf还有其他选择吗?

(在Godbolt上玩这个播放 https://godbolt.org/z/fmo8etjnr

For example say I have a class Foo with a typical serialization pattern.

struct Foo {
    int a;
    bool b;
    template <typename Archive>
    void serialize(Archive & ar) {
        ar & a;
        ar & b;
    }
};

Now suppose somebody comes along and adds a field.

struct Foo {
    int a;
    bool b;
    std::string c;

    template <typename Archive>
    void serialize(Archive & ar) {
        ar & a;
        ar & b;
    }
};

This compiles just fine but the Archive method is wrong. I could add something like


namespace detail {
template <int a, int b>
void AssertSizeOfImplementation() {
    static_assert(a == b, "Size does not match (check stack trace)");
}
}  
template <typename T, int size>
void AssertSizeOf() {
    detail::AssertSizeOfImplementation<sizeof(T), size>();
}


struct Foo {
    int a;
    bool b;

    template <typename Archive>
    void serialize(Archive& ar) {
        ar& a;
        ar& b;
        AssertSizeOf<Foo,8>();
    }
};

and now if I add the extra field I will see a compile error

: In instantiation of 'void detail::AssertSizeOfImplementation() [with int a = 40; int b = 8]':

I can then fix my serialization code and update the assertion.

However this is not very portable. sizeof will return different results depending on packing and architecture.

Are there any other alternatives to using sizeof?

( play with this on godbolt https://godbolt.org/z/fMo8ETjnr )

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无边思念无边月 2025-02-06 10:50:31

boost中有很酷的库: boost pfr 。我从未在真实的项目(只是一些玩具)中使用过它,但似乎运行良好:

struct Foo {
    int a;
    bool b;

    template <typename Archive>
    void serialize(Archive& ar, const unsigned int)
    {
        boost::pfr::for_each_field(*this, [&ar](const auto& field) { ar& field; });
    }
};

现在,将考虑任何字段列表的任何更改,而无需更改序列化代码。

我尝试了Godbolt,但我未能解决链接问题(找不到Boost库),因此实际上可以运行。

There is cool library in boost: boost pfr. I never used it in real project (just some toys), but seems to work quite well:

struct Foo {
    int a;
    bool b;

    template <typename Archive>
    void serialize(Archive& ar, const unsigned int)
    {
        boost::pfr::for_each_field(*this, [&ar](const auto& field) { ar& field; });
    }
};

Live demo.

Now any change in list of fields will be taken into account without need to alter serialization code.

I tried on godbolt, but I've failed to resolve linking issues (can't find boost libraries), so it could actually run.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文