Search code examples
c++boostshared-ptrboost-serialization

Serialize and deserialize boost shared pointers


I know there is the chance to use methods created by boost in order to serialize shared pointers, but I've created this:

namespace boost { namespace serialization {

template<class Archive, class T>
inline void serialize(Archive& ar, boost::shared_ptr<T>& b, const unsigned int file_version)
{
    // serialize a string which is the key of the pointer
}

} }

Now I'd like to handle the deserialization in the same way. So, I'd like to take the serialized key and get the object in some map.

How can I handle this in the deserialization?


Solution

  • It looks to me you might simply be "optimizing" to avoid duplicate serialized objects.

    Boost Serialization already has this feature builtin for (smart) pointers¹: Object Tracking

    Here's a demo of what it means for your sample:

    Live On Coliru

    #include <boost/archive/text_iarchive.hpp>
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/unordered_map.hpp>
    #include <boost/serialization/shared_ptr.hpp>
    #include <boost/serialization/vector.hpp>
    #include <iostream>
    
    struct HeyHey {
    
        std::string name;
        HeyHey(std::string n = "") : name(n) {}
    
      private:
        friend class boost::serialization::access;
        template <typename Ar> void serialize(Ar& ar, unsigned) { ar & name; }
    };
    
    using HeyPtr = std::shared_ptr<HeyHey>;
    
    int main() {
    
        std::stringstream ss;
    
        {
            std::vector<HeyPtr> ptrs = { 
                std::make_shared<HeyHey>("one"),
                std::make_shared<HeyHey>("two"),
                std::make_shared<HeyHey>("three"),
                std::make_shared<HeyHey>("four"),
            };
    
            std::unordered_map<int, HeyPtr> m = {
                { 1, ptrs[0] },
                { 2, ptrs[1] },
                { 3, ptrs[2] },
                { 4, ptrs[3] },
            };
    
            boost::archive::text_oarchive oa(ss);
            oa << ptrs << m;
        }
    
        {
            std::vector<HeyPtr> ptrs;
            std::unordered_map<int, HeyPtr> m;
    
            boost::archive::text_iarchive ia(ss);
            ia >> ptrs >> m;
    
            std::cout << "Deserialized:\n";
            for (auto p : m) {
                std::cout << "Key: " << p.first << " mapped to " << std::quoted(p.second->name) << " at address " << p.second.get() << "\n";
            }
    
            std::cout << "Vector contains: ";
            for (auto sp: ptrs)
                std::cout << sp.get() << " ";
    
            std::cout << "\n";
        }
    
    }
    

    Prints:

    Deserialized:
    Key: 1 mapped to "one" at address 0x25de420
    Key: 2 mapped to "two" at address 0x25de450
    Key: 3 mapped to "three" at address 0x25de4b0
    Key: 4 mapped to "four" at address 0x25de480
    Vector contains: 0x25de420 0x25de450 0x25de4b0 0x25de480 
    

    Note how the map and the vector point to the same HeyHey instances: the aliases pointers were tracked by the archive and only got (de)serialized once.

    ¹ and, with some help, for references