Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialization of STL unordered_map

I have a program which uses an unordered map with this definition:

unordered_map<const char*, vector<pair<int, int> >, function<unsigned int (const char *str)> > myMap(30000, hashing);

where hashing is a function used for, well, hashing keys. My problem is -> how to serialize this kind of structure and deserialize it afterwards? I really need that, and to be fast and efficient as possible. I have been reading about boost libraries, but I don't understand much how to use them with this kind of stuff. I know there is some boost library for unordered maps, but, obviously I'm doing something wrong with it and the compiler throws a lot of errors. Can someone give me an example code that works on how to serialize this? Thanks.

like image 941
darxsys Avatar asked Dec 26 '22 13:12

darxsys


1 Answers

TL;DR You cannot serialize std::function, use a regular predicate class instead.


Serializing a map (whatever its kind) is easy. At heart it is:

typedef std::map<std::string, std::string> Map;

void serialize(Serializer& out, Map const& map) {
    out << map.size();
    for (auto const& p: map) { out << p.first << p.second; }
}

Map deserialize(Deserializer& in) {
    Map map;

    size_t size = 0;
    in >> size;

    for (size_t i = 0; i != size; ++i) {
        Map::key_type key;
        Map::mapped_type value;
        in >> key >> value;
        map[key] = value;
    }

    return map;
}

Except that in the general case both the comparator and allocator could be stateful right ?

void serialize(Serializer& out, Map const& map) {
+   out << map.value_compare() << map.get_allocator();

    out << map.size();
    for (auto const& p: map) { out << p.first << p.second; }
}

Map deserialize(Deserializer& in) {
+   Map::key_compare comparator;
+   Map::allocator_type allocator;
+
+   in >> comparator >> allocator;
+
+   Map map(comparator, allocator)

    size_t size = 0;
    in >> size;
    for (size_t i = 0; i != size; ++i) {
        Map::key_type key;
        Map::mapped_type value;
        in >> key >> value;
        map[key] = value;
    }

    return map;
}

So, in your case, assuming that Boost.Serialization knows how to handle std::allocator (it's stateless), how is it supposed to serialize std::function<unsigned int(char const*)> ?

Answer: it's impossible because std::function performs type erasure and this clashes with C++ statically typed nature (and its lack of introspection). Once a type has been erased, it is not possible, in general, to recover it.

You need the type of the comparator to be explicit in the type of the map OR to have an external mean to look it up. In any case, it may be hard to fit it into Boost.Serialization (context-less). You will probably be better up using a regular predicate class.

like image 55
Matthieu M. Avatar answered Dec 29 '22 03:12

Matthieu M.