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,
source to share
There is end-to-end support for Boost multithreaded serialization:
Classes
number
,debug_adaptor
,logged_adaptor
andrational_adaptor
have a "pass-through" support for serialization, which requires a basic backend for serialization.Backends
cpp_int
,cpp_bin_float
,cpp_dec_float
andfloat128
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;
}
}
source to share