valdo
valdo

Reputation: 12943

Inheriting an std::container including its boost serialization

I have a class defined this way:

template <typename T>
class MyMap
    :public std::map<MyKey, T>
{
    // ...
};

This class doesn't add any members, it just wraps the std::map and provides some auxiliary functions (for convenience).

Now, my goal is to make this class boost-serialization-compatible. That is, not only I need to support serialization, it also should be compatible with the serialization of the std::map with the same template parameters.

How to achieve this? I tried to leave the class as-is (hoping it'll derive the serialization from the base class) - doesn't compile. Tried to add a trivial implementation of serialize that calls the base - doesn't compile.

I also tried to add my implementation. It's ok, but it's not compatible with that of std::map.

Any ides? Thanks in advance.

Thanks in advance.

Upvotes: 0

Views: 205

Answers (3)

Yochai Timmer
Yochai Timmer

Reputation: 49261

You can force instantiation of the boost::serialization::implementation_level_impl inside your class. (that's what's created by BOOST_CLASS_IMPLEMENTATION)

In your case, something like this will work:

template <typename T>
class MyMap
    :public std::map<MyKey, T>
{
    boost::serialization::implementation_level_impl<MyMap<T>> temp; //Causes template instantiation
};

namespace boost {                                    
    namespace serialization {      
        template <typename T>
        struct implementation_level_impl< const MyMap<T> >                     
        {                                                    
            typedef mpl::integral_c_tag tag;                 
            typedef mpl::int_< boost::serialization::object_serializable > type;                     
            BOOST_STATIC_CONSTANT(                           
                int,                                         
                value = implementation_level_impl::type::value    
                );                                               
        };                                                   
    }                                                    
}

Upvotes: 0

Yochai Timmer
Yochai Timmer

Reputation: 49261

Read the base classes section in the Serialization documentation

template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
    ar & boost::serialization::base_object<std::map<MyKey, T>>(*this);

    //Serialize your stuff after the base class
}

Upvotes: 1

tmaric
tmaric

Reputation: 5477

From the section 6.7 of the book The C++ Standard Library: A Tutorial and Reference:

There are three different approaches to making containers "STL-able":

  1. The invasive approach:

Instead of invasive and noninvasive sometime the terms intrusive and nonintrusive are used. You simply provide the interface that ah STL container requires. In particular, you need the usual member functions of containers such as begin() and end(). This approach is invasive because it requires that a container be written in a certain way.

  1. The noninvasive approach:

You write or provide special iterators that are used as an interface between the algorithms and special containers. This approach is noninvasive. All it requires is the ability to step through all of the elements of a container, an ability that any container provides in some way.

  1. The wrapper approach

Combining the two previous approaches, you write a wraper class that encapsulates any data structure with an STL container-like interface.

If you mean to support an additional/different functionality to std::map with the wrapper approach, you should encapsulate the map within a wrapper class, and not inherit from std::map.

Upvotes: 0

Related Questions