2016-03-25 10 views
1

私はstd::unordered_map<std::type_index, MyProperty>MyClassに格納するためにstd::type_indexを使っています。今私はブースト::シリアル化MyClassとシリアル化したいと思います。コンパイラはstruct std::type_index has no member named serializeと言っています。これはboost :: serializationがstd::type_indexをサポートしていないことを示しています。だから問題は、この場合に何をすべきかということです。誰でものserialize機能を持っていますか?または、同じ種類のことをすることができる、すでにシリアライズ可能なこのmapのキーに使用できる別のオブジェクトがあります。関数テンプレートを使用している場合つまり、私が行います`std :: type_index`をシリアライズ

#include <boost/archive/text_oarchive.hpp> 

#include <fstream> 
#include <typeindex> 

int main() 
{ 
    std::type_index myTypeIndex = typeid(double); 

    std::ofstream outputStream("test.txt"); 
    boost::archive::text_oarchive outputArchive(outputStream); 

    outputArchive << myTypeIndex; 
    outputStream.close(); 

    return 0; 
} 
+0

危険です。先の地雷畑。コンパイラによって構築されたものではなく、構築できるものにインデックスを付けたいと思うでしょう。残念ながら、typeidの周りに独自の多型、直列化可能なラッパーを作成する必要があります。 –

+0

@RichardHodges 'std :: unordered_map を使うのは、一般的には悪い考えですか?それとも、シリアル化する必要があるときだけですか? –

+0

いいえ、type_indexはインデックスとして使用するように設計されています。あなたが構築を制御していないので、単にboost :: serializeと互換性がありません。少なくとも、カスタムのロード/ストア関数を提供する必要があります。 –

答えて

1

ステップ1:ここでは

template <typename T> 
void MyClass::func(T) 
{ 
    myMap.find(std::type_index(typeid(T))); 
} 

はサポートの欠如のデモではstd用に独自 boost::serialization::load/save<>のオーバーロードを定義します:: type_index

ステップ2:文字列をtype_indexにマッピングする手段を提供します。

手順3:type_indexをアーカイブの名前で格納します。

もちろん、地図にキーとして使用するすべてのタイプの名前を登録することを忘れないでください。下の例では、register_name("Foo", typeid(Foo));などを呼び出してこれを行います。

#include <iostream> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/serialization/split_free.hpp> 

#include <fstream> 
#include <sstream> 
#include <typeindex> 
#include <tuple> 
#include <vector> 
#include <string> 

struct nothing {}; 

using named_typeindex = std::tuple<std::string, std::type_index>; 
std::vector<named_typeindex> name_register = 
{ 
}; 

std::type_index type_for_name(const std::string& name) 
{ 
    auto i = std::find_if(std::begin(name_register), std::end(name_register), 
          [&name](const auto& entry) { return std::get<std::string>(entry) == name; }); 
    if (i == std::end(name_register)) 
     return typeid(nothing); 
    return std::get<std::type_index>(*i); 
} 

std::string const& name_for_type(std::type_index type) 
{ 
    auto i = std::find_if(std::begin(name_register), std::end(name_register), 
          [type](const auto& entry) { return std::get<std::type_index>(entry) == type; }); 

    using namespace std::string_literals; 
    if (i == std::end(name_register)) 
     throw std::logic_error("unregistered type "s + type.name()); 

    return std::get<std::string>(*i); 
} 

bool register_name(std::string name, std::type_index ti) 
{ 
    if (type_for_name(name) == typeid(nothing)) 
    { 
     name_register.push_back(std::make_tuple(std::move(name), ti)); 
     return true; 
    } 
    return false; 
} 

namespace boost { 
    namespace serialization { 

     template<class Archive> 
     void save(Archive & ar, const std::type_index & t, unsigned int version) 
     { 
      ar << name_for_type(t); 
     } 

     template<class Archive> 
     void load(Archive & ar, std::type_index & t, unsigned int version) 
     { 
      std::string s; 
      ar >> s; 
      t = type_for_name(s); 
     } 

    } // namespace serialization 
} // namespace boost 

BOOST_SERIALIZATION_SPLIT_FREE(std::type_index); 

int main() 
{ 
    std::type_index myTypeIndex = typeid(double); 

    std::ostringstream outputStream {}; 
    boost::archive::text_oarchive outputArchive(outputStream); 

    outputArchive << myTypeIndex; 

    std::cout << outputStream.str() << std::endl; 

    return 0; 
} 
関連する問題