2011-02-09 2 views
3

ユーザ定義型の格納とシリアライズを処理するライブラリを作成しています。ユーザー定義型は、それ自体がシリアライズ可能である必要があります。ユーザ提供の派生型をBoost Serializationに登録する

ただし、ライブラリはテンプレートを使用してユーザータイプのコンテナを作成します。私はテンプレートを介して::シリアル化を強化するコンテナの種類をエクスポートする方法を知りません。私が行うことができる唯一の方法は、ライブラリのユーザがBOOST_CLASS_EXPORT_GUID()にすべてのコンテナタイプを強制的に渡すことです。

私はboost/serialization/export.hppを見てマクロをアンパックしようとしましたが、少し複雑です...クラスをテンプレートインスタンス化の一部としてエクスポートする方法はありますか?または、ユーザー定義型のコンテナを簡単にシリアル化するためにライブラリを書き込む別の方法はありますか?たぶん

#include <iostream> 
#include <vector> 

#include <boost/foreach.hpp> 
#include <boost/serialization/access.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/base_object.hpp> 
#include <boost/serialization/export.hpp> 

#include <boost/archive/text_oarchive.hpp> 

////////////////////////////////////////////////////////////////////////////// 
// Example code that would reside in the library 
////////////////////////////////////////////////////////////////////////////// 

struct type_container_base { 
private: 
    virtual void make_abstract() const {} 
    friend class ::boost::serialization::access; 
    template <typename ARCHIVE> 
    void serialize(ARCHIVE &, const unsigned int) {}  
}; 

BOOST_SERIALIZATION_ASSUME_ABSTRACT(type_container_base) 

template <typename USER_TYPE> 
struct type_container : type_container_base { 
    void add(const USER_TYPE& d) { _vector.push_back(d); } 
private: 
    std::vector<USER_TYPE> _vector; 
    friend class ::boost::serialization::access; 
    template <typename ARCHIVE> 
    void serialize(ARCHIVE & ar, const unsigned int) { 
     ar & ::boost::serialization::base_object<type_container_base>(*this); 
     ar & _vector; 
    } 
}; 

////////////////////////////////////////////////////////////////////////////// 
// Example user code that would use the library 
////////////////////////////////////////////////////////////////////////////// 

struct user_type { 
    user_type(int i) : _val(i) {} 
private: 
    int _val; 
    friend class ::boost::serialization::access; 
    template <typename ARCHIVE> 
    void serialize(ARCHIVE & ar, const unsigned int) { 
     ar & _val; 
    } 
}; 

// *** Is there a better way than forcing the user to do this for every 
// *** user_type they want to use with the library? 
BOOST_CLASS_EXPORT_GUID(type_container<user_type>, "type_container<user_type>") 

int main() { 
    std::vector<type_container_base*> containers; 
    type_container<user_type>* tc = new type_container<user_type>(); 
    tc->add(user_type(7)); 
    tc->add(user_type(42)); 
    tc->add(user_type(1776)); 
    containers.push_back(tc); 
    { 
     boost::archive::text_oarchive ar(std::cout); 
     const std::size_t size = containers.size(); 
     ar << size; 
     BOOST_FOREACH(type_container_base* p, containers) 
      ar << p; 
    } 
    return 0; 
} 

答えて

0

これらの線に沿って何か:

#define BOOST_CLASS_TEMPLATE_EXPORT_IMPLEMENT(T)    \ 
    namespace boost {          \ 
    namespace archive {          \ 
    namespace detail {          \ 
    namespace {            \ 
    template<typename U>          \ 
    struct init_guid< T<U> > {        \ 
     static guid_initializer< T<U> > const & g;   \ 
    };              \ 
    template<typename U>          \ 
    guid_initializer< T<U> > const & init_guid< T<U> >::g = \ 
     ::boost::serialization::singleton<     \ 
      guid_initializer< T<U> >       \ 
     >::get_mutable_instance().export_guid();    \ 
    }}}}              \ 
/**/ 

#define BOOST_CLASS_TEMPLATE_EXPORT_KEY2(T, K) \ 
namespace boost {        \ 
namespace serialization {      \ 
template<typename U>       \ 
struct guid_defined< T<U> > : boost::mpl::true_ {}; \ 
template<typename U>       \ 
inline const char * guid< T<U> >(){   \ 
    return K + "<" + guid<U>() + ">"; //this doesn't work, I know! \ 
}            \ 
} /* serialization */       \ 
} /* boost */         \ 
/**/ 

#define BOOST_CLASS_TEMPLATE_EXPORT_KEY(T)        \ 
    BOOST_CLASS_TEMPLATE_EXPORT_KEY2(T, BOOST_PP_STRINGIZE(T))               \ 
/**/ 

#define BOOST_CLASS_TEMPLATE_EXPORT_GUID(T, K)       \ 
BOOST_CLASS_TEMPLATE_EXPORT_KEY2(T, K)         \ 
BOOST_CLASS_TEMPLATE_EXPORT_IMPLEMENT(T)        \ 
/**/ 

それはそれにいくつかの追加の調整で動作する可能性があります。もちろん、おそらくuser_typeも既にエクスポートされていると仮定します。しかし、コンビナトリアルディメンションを減らすことができます。クラスごとに1つのエクスポートと、クラスごとに1つのエクスポートが必要です。テンプレートインスタンシエーションごとに1つのエクスポート(クラスの数Xクラスの数)ではありません。

これはおそらく、Boost.Serializationライブラリ担当者(私はそれがRobert Rameyだろうと思います)に質問/要求/提案されるべきものです。

+0

うーん...そこに何かがあるかもしれません。ちょうど明確にするために、私の問題は、コンテナ型をエクスポートしていません、それは私のパラメータがまだ知られていないテンプレートの特殊化された型をエクスポートすることはできません。これは、BOOST _...マクロが名前空間のスコープで動作するためです。そのため、ユーザーは型のエクスポート(および/または関連するコンテナのタイプ)を処理する必要があります。一方、私はライブラリがそれを扱うことを望んでいます。おそらく、シリアライズライブラリに直接プラグインすることによって可能です。 – vsekhar