2016-04-25 10 views
1

TLDR:クラスのシリアル化を実装レベルobject_class_infoからobject_serializableに移行し、古いデータファイルとの互換性を保ちながら、常に新しいフォーマットでファイルを書きたいと思います。ブーストシリアル化:バージョン化されたクラスからobject_serializableへの移行

理由:ブーストシリアライゼーションライブラリを使用し始めたとき、私には既にをシリアル化するためのヘッダ(complex.hpp)が付いていたことに気づいていませんでした。代わりに、私は私自身、自立シリアライズ機能を書いた:デフォルトで

namespace boost { namespace serialization { 
    template<class Archive, typename T> 
    void serialize(Archive& ar, std::complex<T>& comp, const unsigned int version) { 
    ar & reinterpret_cast<T(&)[2]>(comp)[0]; 
    ar & reinterpret_cast<T(&)[2]>(comp)[1]; 
    } 
} 

これはかなりダウンコードを遅くバージョンとクラス情報の追跡を可能に。 Boostに付属しているシリアライゼーション機能はかなり高速です。

新しいデータファイルを書き出すときに常にBoostバージョンを使用するように移行したいが、それでも古いデータファイルを読み込めるようにする。古いバイナリで新しいファイルを読むことは問題ではありません。

問題は、新しいシリアル化がバージョン管理されていないことです(明らかに)。さらに、古いバージョンのコードを使ってアーカイブを読み込み、直ちに新しいバージョンを使用して書き直そうとすることもできません。デシリアライズ/シリアライゼーションの特性はグローバルプロパティです。

a)常に新しいファイルを書き込んだりしながら古いファイルと新しいファイルを透過的に読み取るか、b)古いファイルを読み込んですぐに新しいフォーマットで書き出すかのいずれかを行うにはどうすればよいでしょうか?

+0

を設定することができ、「古いバイナリと新しいファイルで読むことは問題ではない」 - ことを何をしますかmean – sehe

+0

@sehe:新しいコードからコンパイルされた新しいバイナリを使って古いデータファイルを読みたい。以前のバージョンのコードから既存のバイナリを使用して新しいデータファイルを読み込むことは望ましくありません。 – Claudius

答えて

1

ファイルのバージョンが「古い」場合は、古い実装をそのまま使用できます。

複雑なシリアライズのブースト版は、保存時またはファイルのバージョンが「新規」の場合にのみ使用します。

あなたはシリアル化する複雑なデータを含むオブジェクトを持っている場合に、簡単なラッパーを使用して、この

UPDATE

サンプルを達成するために含まれるオブジェクトにバージョンをバンプすることができますので、これは、些細でなければなりません

Live On Coliru

:シリアライズの古いスタイルを呼び出します枚の
#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/serialization/complex.hpp> 

template <typename T> struct old_format_wrapper { 
    T& wrapped; 
    old_format_wrapper(T& w) : wrapped(w) {} 
}; 

template <typename T> 
old_format_wrapper<T> old_format(T& w) { return {w}; } 

namespace boost { namespace serialization { 
    template<class Archive, typename T> 
     void serialize(Archive& ar, old_format_wrapper<std::complex<T> >& comp, unsigned) { 
      ar & reinterpret_cast<T(&)[2]>(comp.wrapped)[0]; 
      ar & reinterpret_cast<T(&)[2]>(comp.wrapped)[1]; 
     } 
} } 

struct IHaveComplexData { 
    std::complex<double> data; 

    template <typename Ar> void serialize(Ar& ar, unsigned version) { 
     switch(version) { 
      case 0: { // old 
        auto wrap = old_format(data); 
        ar & wrap; 
       } 
       break; 
      case 1: // new 
      default: 
       ar & data; // uses boost serialization 
       break; 
     } 
    } 
}; 

int main() { 
    { 
     boost::archive::text_oarchive oa(std::cout); 
     IHaveComplexData o { { 2, 33 } }; 
     oa << o; 
    } 

    { 
     std::istringstream iss("22 serialization::archive 13 0 0 0 0 2.00000000000000000e+00 3.30000000000000000e+01"); 
     boost::archive::text_iarchive ia(iss); 
     IHaveComplexData o; 
     ia >> o; 
     std::cout << o.data; 
    } 
} 

プリント(あなたのブーストバージョンによって異なります):もちろん

22 serialization::archive 13 0 0 0 0 2.00000000000000000e+00 3.30000000000000000e+01 
(2,33) 

、あなたが今BOOST_CLASS_VERSION(IHaveComplexData, 1)

+0

このタイプを含む多くのオブジェクトがあり、 'serialize'の周りのBoostラッパーがバージョン番号を期待しているので、これはうまくいきません。つまり、Boostにはバージョン管理された型が予期されることがあります(同じクラスの場合もあります)。 – Claudius

+0

シリアル化フォーマットは、あなたのタイプのプロパティです。あなたは、難しい/退屈な/不可能なもののサンプルを私に見せてもらえますか? – sehe

+0

Boostのシリアライゼーションライブラリは、クラスのバージョニング、クラス名などの扱いにくいビットの大部分を処理します。次に、シリアライズしたいクラスの 'serialize()'関数を呼び出します。問題は、このクラスのバージョン化/その他のオーバーヘッド、すなわちBoostライブラリが期待する追加情報が、直列化されたクラスの型特性によって支配されることである。私の質問は、基本的には、プログラムの一部(読み込みビット)でオン/オフをどのようにオンにすることができるかです。 – Claudius

関連する問題