2011-11-01 171 views
1

我正在使用yaml-cpp進行某種類型的序列化。對於這項工作的每個類都有使用簽名來聲明一個方法:yaml-cpp,YAML :: Node和一個模板操作符>>

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

T是不同的類保存和加載時。這兩個類的接口是相同的,但我不能創建抽象基類,因爲大多數方法都是模板。這部分工作正常。我試圖把它與YAML::Nodeoperator>>YAML::Emitteroperator<<聯繫起來。

對於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>>,但它沒有奏效。它看起來像這樣:

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)和鐺(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支持的正常類型一樣。

回答

0

首先,關於reinterpret_cast:您實際上需要static_cast。在你的情況下,你知道val a T(不只是一個Serializable<T>),所以你可以直接施放它。

在這裏,我假設你像聲明

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

reinterpret_cast你的類將解釋的val字節T,這是不能保證的工作,但可能工作在你的因爲您有單一繼承,並且Serializable<T>不會添加任何成員變量。

接下來,就您真正的問題:這是yaml-cpp中的一個錯誤,現在它已修復(如果您正在跟蹤mercurial存儲庫,並且對於我打開的問題,請參閱http://code.google.com/p/yaml-cpp/issues/detail?id=126)(r52790a15757d)。

有了上述修復,我相信你的代碼應該可以工作。如果你沒有跟上版本庫,那麼差異很小 - 你可以在你的yaml-cpp版本中打補丁。

+0

奇怪,我試過'static_cast',它沒有工作,但現在它的工作。 (也許我試圖投到T,而不是T *?)。無論如何,你的補丁很好,感謝修復。 –