yaml-cpp、YAML::Node 和模板运算符 >>

发布于 2024-12-12 21:35:43 字数 1683 浏览 2 评论 0 原文

我正在使用 yaml-cpp 进行某种序列化。为此,每个类都必须使用签名声明一个方法:

template <typename T> void Serialize(T& s);

在保存和加载时,T 是不同的类。这两个类的接口是相同的,但我不能创建一个抽象基类,因为大多数方法都是模板。这部分工作正常。我尝试将其与 YAML::Nodeoperator>>YAML::Emitter 连接起来运算符<<

对于operator<<,我有一个可行的解决方案,尽管非常残酷。首先为所有可序列化类声明一个超类:

template <typename T> class Serializable {};

然后我可以使用以下运算符<<:

template <typename T>
YAML::Emitter& operator<<(YAML::Emitter& out,
                          Serializable<T>& val)
{
    Serializer serializer(out);
    reinterpret_cast<T*>(&val)->Serialize(serializer);
    return out;
}

到目前为止,这有效,尽管 reinterpret_cast 看起来非常可怕,而且我'我不确定这是否合法。我对 operator>> 进行了相同的尝试,但没有成功。它看起来像这样:

template <typename T>
void operator>>(const YAML::Node& node,
                Serializable<T>& val)
{
    Deserializer deserializer(node);
    reinterpret_cast<T*>(&val)->Serialize(deserializer);
}

但是 gcc (4.6.2) 和 clang(2.9) 都忽略它,并使用在 nodeimp.h (yaml-cpp 的一部分)中定义的 operator>>

template <typename T>
inline void operator >> (const Node& node, T& value) {
    if(!ConvertScalar(node, value))
        throw InvalidScalar(node.m_mark);
}

所以我的问题是:我应该如何解决这个问题?我绝对想要的是只有一个方法用于序列化和反序列化,并且能够使用>>和 <<,就像它是 yaml-cpp 支持的普通类型一样。

I'm making some kind of serialization using yaml-cpp. For this to work each class has to declare a method using the signature:

template <typename T> void Serialize(T& s);

That T is a different class when saving and loading. The two class's interface is the same, but I can't make an abstract base class, since most methods are templates. This part is working correctly. I've tried to hook it up with YAML::Node's operator>> and YAML::Emitter's operator<<.

For operator<<, I have a working solution, albeit very cruel one. First declare a superclass for all serializable classes:

template <typename T> class Serializable {};

Then I can use the following operator<<:

template <typename T>
YAML::Emitter& operator<<(YAML::Emitter& out,
                          Serializable<T>& val)
{
    Serializer serializer(out);
    reinterpret_cast<T*>(&val)->Serialize(serializer);
    return out;
}

This works so far, even though that reinterpret_cast looks pretty scary, and I'm not sure if it's even legal. I've tried the same for operator>>, but it didn't work. It looks like this:

template <typename T>
void operator>>(const YAML::Node& node,
                Serializable<T>& val)
{
    Deserializer deserializer(node);
    reinterpret_cast<T*>(&val)->Serialize(deserializer);
}

But gcc (4.6.2) and clang(2.9) both ignore it, and use the operator>> defined in nodeimp.h (part of yaml-cpp):

template <typename T>
inline void operator >> (const Node& node, T& value) {
    if(!ConvertScalar(node, value))
        throw InvalidScalar(node.m_mark);
}

So my question is: how should I solve this? Things I absolutely want is to only have a single method for both serialization and deserialization, and to be able to use >> and <<, like if it was a normal type supported by yaml-cpp.

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

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

发布评论

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

评论(1

抹茶夏天i‖ 2024-12-19 21:35:43

首先,关于reinterpret_cast:您实际上需要static_cast。就您而言,您知道 val T (而不仅仅是 Serialized),因此你可以直接投射它。

在这里,我假设您声明的类如

class Foo: public Serializable<Foo> { ... };

reinterpret_cast 会将 val字节 解释为 T,这不能保证有效,但可能适用于您的情况,因为您具有单一继承,并且 Serialized 不添加任何成员变量。

接下来,解决您真正的问题:这是 yaml-cpp 中的一个错误,现已修复(r52790a15757d 如果您正在关注 Mercurial 存储库,请参阅 http://code.google.com/p/yaml-cpp/issues /detail?id=126 对于我打开的问题)。

通过上述修复,我相信您的代码应该可以工作。如果您没有跟上存储库,那么差异非常小 - 您可以在您的 yaml-cpp 版本中修补它。

First, about reinterpret_cast: you actually want static_cast. In your case, you know that val is a T (not just a Serializable<T>), so you can cast it directly.

Here, I'm assuming you're declaring your classes like

class Foo: public Serializable<Foo> { ... };

reinterpret_cast will interpret the bytes of val as a T, which isn't guaranteed to work, but probably works in your case because you have single inheritance and Serializable<T> doesn't add any member variables.

Next, on to your real problem: this is a bug in yaml-cpp, and it's now fixed (r52790a15757d if you're keeping up with the mercurial repository, and see http://code.google.com/p/yaml-cpp/issues/detail?id=126 for the issue I opened).

With the above fix, I believe your code should work. If you don't keep up with the repository, then the diff is pretty small - you can patch it in your version of yaml-cpp.

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