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

前端 未结 1 859
孤城傲影
孤城傲影 2020-12-21 23:18

I have the following template class:

#include 
#include 
#include 
#include 

        
相关标签:
1条回答
  • 2020-12-22 00:05

    There's passthrough support for Boost Multiprecision serialization:

    Classes number, debug_adaptor, logged_adaptor and rational_adaptor have "pass through" serialization support which requires the underlying backend to be serializable.

    Backends cpp_int, cpp_bin_float, cpp_dec_float and float128 have full support for Boost.Serialization.

    That is to say, it's supported iff the backend supports it: mailing list:

    > Does/will multiprecesion have support for boost::serialization?

    Good question, and no not yet. I guess it should do though... it's hard though as some backends (for example GMP's mpf_t) don't round trip to and from string representations, and have an internal structure that probably shouldn't be relied upon :-

    You can:

    • use cpp_rational (as it is supported implicitly by the above doc excerpt)
    • use Boost Rational: How to serialize boost::rational
    • use raw mpz_* API to serialize, see e.g. How to serialize a GMP rational number?

    • you can explicitly add serialization support for the backend (note that using the gmp API's 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 demo Live On Coliru with a simple roundtrip test.

    Full Listing

    #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 讨论(0)
提交回复
热议问题