2

我想序列化一个包含 boost::multiprecision::mpfr_float 作为成员的自定义类。它在 Boost.Serialization 文档中T,如果 5 个属性中的至少一个为真,则类型是可序列化的,而Multiprecision 文档中,number该类具有传递支持,这需要底层后端可序列化。

对于 Boost.Multiprecision 的mpfr_float类型,我知道:

  1. 它不是原始类型。
  2. 它是一个类类型,但它没有serialize定义函数。
  3. 它不是指向 Serializable 类型的指针。
  4. 它不是对 Serializable 类型的引用。
  5. 它不是 Serializable 类型的本机 C++ 数组。

因此,看起来如果我想序列化 mpfr_float 类型,我必须为该类型提供serialize函数。

我的问题是:如何mpfr_float通过自己编写serialize函数将类型扩展为可序列化?我想我需要访问 mpfr 后端,并使用底层数据,但我不确定如何继续。来自有经验的人的提示 Boost 序列化以前未序列化的类将不胜感激。


结论性解决方案

根据 sehe 的回复,我得出了一个解决方案,该解决方案可以以 100 和 1000 的精度进行往返:

namespace boost { namespace serialization { // insert this code to the appropriate namespaces


/**
 Save a mpfr_float type to a boost archive.
 */
template <typename Archive>
void save(Archive& ar, ::boost::multiprecision::backends::mpfr_float_backend<0> const& r, unsigned /*version*/)
{
    std::string tmp = r.str(0, std::ios::fixed);// 0 indicates use full precision
    ar & tmp;
}

/**
 Load a mpfr_float type from a boost archive.
 */
template <typename Archive>
void load(Archive& ar, ::boost::multiprecision::backends::mpfr_float_backend<0>& r, unsigned /*version*/)
{
    std::string tmp;
    ar & tmp;
    r = tmp.c_str();
}

} } // re: namespaces

该方案解决了上述第(2)项的需要,即需要添加serialize功能。谢谢您的帮助。

4

2 回答 2

1

直通支持意味着您确实必须为后端类型添加序列化。

您可以使用与我在此答案中显示的方法相同的方法:

我在这里展示如何(反)序列化mpq_rational

于 2015-02-24T20:31:54.253 回答
0

如果您使用的是版本4.0.0或更高版本,则可以使用mpfr_fpif_exportandmpfr_fpif_import对其进行序列化/反序列化。

using realtype = number<mpfr_float_backend<100, allocate_stack>>;

#define MPFR_BUFFER_SIZE 1000

    namespace boost {
        namespace serialization {
            template<class Archive>
            void save(Archive& ar, const realtype& x, const boost::serialization::version_type&) {
                static char buffer[MPFR_BUFFER_SIZE];
                FILE* fid = fmemopen(buffer, MPFR_BUFFER_SIZE, "wb+");
                mpfr_fpif_export(fid, const_cast<mpfr_ptr>(x.backend().data()));
                fseek(fid, 0L, SEEK_END);
                long length = ftell(fid);
                ar& length;
                ar& boost::serialization::make_array(buffer, length);
                fclose(fid);
            }

            template<class Archive>
            void load(Archive& ar, realtype& x, const boost::serialization::version_type&) {
                static char buffer[MPFR_BUFFER_SIZE];
                long length = 0;

                ar& length;
                ar& boost::serialization::make_array(buffer, length);

                FILE* fid = fmemopen(buffer, length, "r");
                mpfr_fpif_import(x.backend().data(), fid);
                fclose(fid);
            }

            template<class Archive>
            inline void
                serialize(Archive& ar, realtype& t, const unsigned int file_version) {
                split_free(ar, t, file_version);
            }
        }
    }
于 2020-01-04T14:15:04.813 回答