序列化`std :: type_index`

时间:2016-03-25 12:01:05

标签: c++ c++11 serialization boost boost-serialization

我一直在使用std::type_indexstd::unordered_map<std::type_index, MyProperty>中存储MyClass。现在我想序列化(使用boost :: serialization)MyClass。编译器说struct std::type_index has no member named serialize表示boost :: serialization不支持std::type_index。所以问题是,在这种情况下该怎么做?有人serializestd::type_index函数吗?或者是否有一个不同的对象可以用于我需要的map的键,它已经可以序列化,可以执行相同类型的操作。也就是说,当我使用功能模板时:

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

以下是缺乏支持的演示:

#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;
}

1 个答案:

答案 0 :(得分:1)

步骤1:为std :: type_index

定义自己的boost::serialization::load/save<>重载

步骤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;
}