読者です 読者をやめる 読者になる 読者になる

C++と色々

主にC++やプログラムに関する記事を投稿します。

boost::serializationでboost::shared_ptrをシリアライズする

boost::shared_ptrシリアライズする際にハマったのでメモしておきます。

boost::shared_ptrのトラッキングレベルはboost::shared_ptrの型Tのトラッキングレベルに依存しています。そして、その型Tのトラッキングレベルはboost::serialization::track_never以外でなければなりません。このことはboost/serialization/shared_ptr.hppの15行目に、

    // correct shared_ptr serialization depends upon object tracking
    // being used.
    BOOST_STATIC_ASSERT(
        boost::serialization::tracking_level< T >::value
        != boost::serialization::track_never
    );

と書いてあります。

一方で、組み込み型のトラッキングレベルはboost::serialization::track_neverであるという仕様になっています。*1

よって「boost::shared_ptrのトラッキングレベルは要素の型に依存してるけど、track_neverは不可で、しかしintはtrack_nenverと決まっている」という状態になります。このままではboost::shared_ptrシリアライズすることが出来ません。

解決方法は、intをラップしたユーザー定義型を作り、それをboost::shared_ptrの要素の型にします。 例えば

struct Integer
{
    int held = 0;
    operator int() const { return held; }
    Integer(int value) : held(value) {}
    Integer() = default;
};

のようなクラスを作り、それをshared_ptrの要素の型にします。この方法はboost/serialization/shared_ptr.hppの88行目や135行目に下のように書かれています。

    // The most common cause of trapping here would be serializing
    // something like shared_ptr<int>.  This occurs because int
    // is never tracked by default.  Wrap int in a trackable type
    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));

当然ですが、これはint型に限った話ではなく、組み込み型のboost::shared_ptrを作成するときに当てはまります。

*1:http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.htmlのReference>Serializable Concept>Class Serialization TraitsのページのObject TrackingセクションにDefault tracking traits are: For primitive, track_never.とあります