[英]yaml-cpp, YAML::Node, and a template operator >>
我正在使用yaml-cpp進行某種序列化。 為此,每個類都必須使用簽名聲明一個方法:
template <typename T> void Serialize(T& s);
保存和加載時, T
是不同的類。 這兩個類的接口是相同的,但是由於大多數方法都是模板,因此我無法創建抽象基類。 這部分工作正常。 我試圖將其與YAML::Node
的operator>>
和YAML::Emitter
的operator<<
掛鈎。
對於operator<<
,我有一個可行的解決方案,盡管它很殘酷。 首先為所有可序列化類聲明一個超類:
template <typename T> class Serializable {};
然后我可以使用以下operator<<
:
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>>
嘗試了相同的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支持的普通類型一樣。
首先,關於reinterpret_cast
:您實際上需要static_cast
。 在您的情況下,您知道val
是 T
(而不僅僅是Serializable<T>
),因此可以直接將其強制轉換。
在這里,我假設您正在聲明您的課程,例如
class Foo: public Serializable<Foo> { ... };
reinterpret_cast
會將val
的字節解釋為T
,這不能保證能正常工作,但可能會在您的情況下起作用,因為您具有單個繼承並且Serializable<T>
不添加任何成員變量。
接下來,解決您的實際問題:這是yaml-cpp中的錯誤,現在已修復(如果您要跟上Mercurial存儲庫的話, 則已修復r52790a15757d ,請參閱http://code.google.com/p/yaml- cpp / issues / detail?id = 126 (我打開的問題)。
通過以上修復,我相信您的代碼應該可以工作。 如果您不了解存儲庫,那么差異就很小-您可以在yaml-cpp版本中對其進行修補。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.