How to de- / serialize a map with a templating class using boost :: multiprecision :: mpq_rational

I have the following template class:

#include <map>
#include <boost/array.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/multiprecision/gmp.hpp>
template <class T>
class A {
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
        ar & a;
}
public:
  T a;
};

      

which I am using to create the map.

map<A<boost::array<int,2> >, int> mmm;

      

I can use the header files provided by boost to serialize / deserialize this code using:

 ifstream ifs("filename");
 boost::archive::text_iarchive iarch(ifs);
 boost::serialization::load<boost::archive::text_iarchive,int,A<boost::array<int,2> > >(iarch,mmm,1);

      

Question: I would like to use boost::multiprecision::mpq_rational

instead int

inside an array. However, I am getting a long error as the main complaint is that gmp_backend does not have a serialization method:

....
/usr/local/include/boost/serialization/access.hpp:118:9: error: ‘struct boost::multiprecision::backends::gmp_rational’ has no member named ‘serialize’
     t.serialize(ar, file_version);
     ^

      

Is there an easy fix using boost / serialization / map.hpp with mpq_rational? Thank,

+1


source to share


1 answer


There is end-to-end support for Boost multithreaded serialization:

Classes number

, debug_adaptor

, logged_adaptor

and rational_adaptor

have a "pass-through" support for serialization, which requires a basic backend for serialization.

Backends cpp_int

, cpp_bin_float

, cpp_dec_float

and float128

have the full support Boost.Serialization.

That is, it supports if the backend supports it: mailing list :

>

Does / will the multiprocessor have boost :: serialization support?

Good question and not yet. I guess this should happen though ... it's tricky though as some backends (like GMP mpf_t) don't make round trips to and from string representations and have an internal structure that probably shouldn't be relied upon: -

You can:



  • use cpp_rational

    (since this is supported implicitly by the above doc output)
  • use Boost Rational: How to serialize boost :: rational
  • use raw mpz_*

    API for serialization, see for example How to serialize rational GMP number?

  • you can explicitly add serialization support for the backend (note that using the gmp API will be more efficient)

    namespace boost { namespace serialization {
    
        template <typename Archive>
            void save(Archive& ar, ::boost::multiprecision::backends::gmp_rational const& r, unsigned /*version*/)
            {
                std::string tmp = r.str(10000, std::ios::fixed);
                ar & tmp;
            }
    
        template <typename Archive>
            void load(Archive& ar, ::boost::multiprecision::backends::gmp_rational& r, unsigned /*version*/)
            {
                std::string tmp;
                ar & tmp;
                r = tmp.c_str();
            }
    
    } }
    
    BOOST_SERIALIZATION_SPLIT_FREE(::boost::multiprecision::backends::gmp_rational)
    
          

Here's a Live On Coliru demo with a simple round trip test.

Full list

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <boost/multiprecision/rational_adaptor.hpp>
#include <iostream>

namespace boost { namespace serialization {

    template <typename Archive>
        void save(Archive& ar, ::boost::multiprecision::backends::gmp_rational const& r, unsigned /*version*/)
        {
            std::string tmp = r.str(10000, std::ios::fixed);
            ar & tmp;
        }

    template <typename Archive>
        void load(Archive& ar, ::boost::multiprecision::backends::gmp_rational& r, unsigned /*version*/)
        {
            std::string tmp;
            ar & tmp;
            r = tmp.c_str();
        }

} }

BOOST_SERIALIZATION_SPLIT_FREE(::boost::multiprecision::backends::gmp_rational)

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/array.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/serialization.hpp>
#include <map>

template <class T>
class A {
    friend class boost::serialization::access;
    template<class Archive>
        void serialize(Archive & ar, const unsigned int version)
        {
            ar & a;
        }

  public:
    T a;
    bool operator<(A const& o) const { return a<o.a; }
};

#include <sstream>

using KeyElement = boost::multiprecision::mpq_rational;
using Key        = A<boost::array<KeyElement,2> >;
using Data       = std::map<Key, int>;

int main()
{
    std::stringstream ss;
    {
        Data mmm { 
            { Key {{{KeyElement { 1, 2 }, KeyElement { 3, 4 }} }}, 5 }, 
            { Key {{{KeyElement { 6, 7 }, KeyElement { 8, 9 }} }}, 42 },
        };
        boost::archive::text_oarchive oa(ss);

        oa << mmm;
    }

    std::cout << "Serialized:\t" << ss.str() << "\n";

    {
        boost::archive::text_iarchive iarch(ss);
        Data mmm; 
        iarch >> mmm;

        std::cout << "Roundtrip:\t";
        boost::archive::text_oarchive oa(std::cout);
        oa << mmm;
    }
}

      

0


source







All Articles