Deserialization of non-finite floating-point numbe

2019-05-18 12:25发布

问题:

I need to use Boost.Serialization to serialize floating-point numbers. Since NaN and infinites cannot natively be read from an input stream, I am trying to use the facets in boost/math/special_functions. I have tested them on my platform using code similar to the examples we can find here: http://www.boost.org/doc/libs/1_50_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/fp_facets/intro.html However, the following code still fails to properly unserialize non-finite floating point values (an exception is thrown with description "input stream error").

#include <limits>
#include <locale>
#include <sstream>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/math/special_functions/nonfinite_num_facets.hpp>
#include <boost/serialization/nvp.hpp>

struct Data {
        float f;

        Data() : f(std::numeric_limits<float>::quiet_NaN()) {}

        template <class Archive>
        void serialize(Archive & ar, unsigned const)
        {
                ar & BOOST_SERIALIZATION_NVP(f);
        }
};

void test()
{
        using namespace boost::archive;
        Data d;
        std::ostringstream oss;
        xml_oarchive oar(oss);
        oar << BOOST_SERIALIZATION_NVP(d);
        //std::cout << oss.str() << std::endl;
        std::istringstream iss(oss.str());
        std::locale const new_loc(iss.getloc(), new boost::math::nonfinite_num_get<char>);
        iss.imbue(new_loc);
        xml_iarchive iar(iss);
        iar >> BOOST_SERIALIZATION_NVP(d);
        std::cout << d.f << std::endl;
}

Am I doing something wrong? Is there a problem with my Boost version or my platform? Is there a better solution? Any help would be greatly appreciated.

回答1:

I have found the solution by reading the following implementation note: http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/implementation.html#charencoding

When constructing an archive with the default flag, the stream's locale is changed to address character encoding issues, but this mechanism can be disabled using flag boost::archive::no_codecvt.

If I replace the line

xml_iarchive iar(iss);

with

xml_iarchive iar(iss, no_codecvt);

then it works.