C++ 满足Nan和Inf时boost序列化1.5.5崩溃
boost序列化似乎无法从基于文本的存档中恢复值Nan和inf 除非您处理C++ 满足Nan和Inf时boost序列化1.5.5崩溃,c++,boost,boost-serialization,C++,Boost,Boost Serialization,boost序列化似乎无法从基于文本的存档中恢复值Nan和inf 除非您处理archive\u异常,否则程序将终止。在这种情况下,有任何解决方案吗?库的作者: 简单的事实是我从来没有考虑过这个问题。 上次提到这个问题时,我并没有像我想象的那样认真思考 我还参与了其他事情,我希望有兴趣的各方能达成一致 达成共识,而不必弯曲过度伸展的大脑 (继续讨论解决办法) 这似乎是正确的,在我的测试中,只有二进制文件支持inf/nan 除了nan/inf之外,Xml和文本存档确实支持全部精度: using BI
archive\u异常,否则程序将终止。在这种情况下,有任何解决方案吗?库的作者:
简单的事实是我从来没有考虑过这个问题。
上次提到这个问题时,我并没有像我想象的那样认真思考
我还参与了其他事情,我希望有兴趣的各方能达成一致
达成共识,而不必弯曲过度伸展的大脑
(继续讨论解决办法)
这似乎是正确的,在我的测试中,只有二进制文件支持inf/nan
除了nan/inf之外,Xml和文本存档确实支持全部精度:
using BIA = boost::archive::binary_iarchive;
using BOA = boost::archive::binary_oarchive;
using TIA = boost::archive::text_iarchive;
using TOA = boost::archive::text_oarchive;
using XIA = boost::archive::xml_iarchive;
using XOA = boost::archive::xml_oarchive;
int main() {
// supported:
assert((perform_test<BIA, BOA, use_nan, use_inf, use_range>()));
assert((perform_test<XIA, XOA, no_nan, no_inf, use_range>()));
assert((perform_test<TIA, TOA, no_nan, no_inf, use_range>()));
// not supported:
assert(!(perform_test<XIA, XOA, no_nan, use_inf>()));
assert(!(perform_test<TIA, TOA, no_nan, use_inf>()));
assert(!(perform_test<XIA, XOA, use_nan, no_inf>()));
assert(!(perform_test<TIA, TOA, use_nan, no_inf>()));
}
使用BIA=boost::archive::binary\u iarchive;
使用BOA=boost::archive::binary\u oarchive;
使用TIA=boost::archive::text\u iarchive;
使用TOA=boost::archive::text\u oarchive;
使用XIA=boost::archive::xml\u iarchive;
使用XOA=boost::archive::xml\u oarchive;
int main(){
//支持:
断言((perform_test());
断言((perform_test());
断言((perform_test());
//不支持:
断言(!(执行测试());
断言(!(执行测试());
断言(!(执行测试());
断言(!(执行测试());
}
完整列表
为子孙后代:
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <sstream>
using namespace boost::archive;
static bool equal_or_nan(double a, double b) {
return (std::isnan(a) && std::isnan(b)) || a==b;
}
template <typename IA, typename OA,
bool withNan = true,
bool withInf = true,
bool withRange = true>
bool perform_test()
{
std::vector<double> const v {
withRange? std::numeric_limits<double>::min() : 0,
withRange? std::numeric_limits<double>::max() : 0,
withRange? std::numeric_limits<double>::epsilon() : 0,
withNan? std::numeric_limits<double>::quiet_NaN() : 0,
withInf? std::numeric_limits<double>::infinity() : 0,
withInf? - std::numeric_limits<double>::infinity() : 0,
};
std::stringstream ss;
{
OA oa(ss);
oa << boost::serialization::make_nvp("element", v);
}
try
{
IA ia(ss);
std::vector<double> w;
ia >> boost::serialization::make_nvp("element", w);
return std::equal(v.begin(), v.end(), w.begin(), equal_or_nan);
} catch(...) {
return false;
}
}
static constexpr bool use_inf = true, use_nan = true, use_range = true;
static constexpr bool no_inf = false, no_nan = false, no_range = false;
using BIA = boost::archive::binary_iarchive;
using BOA = boost::archive::binary_oarchive;
using TIA = boost::archive::text_iarchive;
using TOA = boost::archive::text_oarchive;
using XIA = boost::archive::xml_iarchive;
using XOA = boost::archive::xml_oarchive;
int main() {
// supported:
assert((perform_test<BIA, BOA, use_nan, use_inf, use_range>()));
assert((perform_test<XIA, XOA, no_nan, no_inf, use_range>()));
assert((perform_test<TIA, TOA, no_nan, no_inf, use_range>()));
// not supported:
assert(!(perform_test<XIA, XOA, no_nan, use_inf>()));
assert(!(perform_test<TIA, TOA, no_nan, use_inf>()));
assert(!(perform_test<XIA, XOA, use_nan, no_inf>()));
assert(!(perform_test<TIA, TOA, use_nan, no_inf>()));
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间boost::archive;
静态布尔等于或等于(双a,双b){
返回(std::isnan(a)和&std::isnan(b))|a==b;
}
模板
布尔执行测试()
{
向量常数v{
withRange?std::numeric_limits::min():0,
withRange?std::numeric_limits::max():0,
withRange?std::numeric_limits::epsilon():0,
withNan?std::numeric_limits::quiet_NaN():0,
withInf?std::numeric_limits::infinity():0,
withInf?-std::数值限制::无穷大():0,
};
std::stringstream-ss;
{
OA(ss);
oa>boost::serialization::make_nvp(“元素”,w);
返回std::equal(v.begin()、v.end()、w.begin()、equal_或_nan);
}捕获(…){
返回false;
}
}
静态constexpr bool use\u inf=true,use\u nan=true,use\u range=true;
静态constexpr bool no_inf=false、no_nan=false、no_range=false;
使用BIA=boost::archive::binary\u iarchive;
使用BOA=boost::archive::binary\u oarchive;
使用TIA=boost::archive::text\u iarchive;
使用TOA=boost::archive::text\u oarchive;
使用XIA=boost::archive::xml\u iarchive;
使用XOA=boost::archive::xml\u oarchive;
int main(){
//支持:
断言((perform_test());
断言((perform_test());
断言((perform_test());
//不支持:
断言(!(执行测试());
断言(!(执行测试());
断言(!(执行测试());
断言(!(执行测试());
}
看一下主题。boost/math/special_函数(参见问题)中有一些方面,以及应用它们的方法(参见答案)。辅助模板函数或重载运算符(例如boost::serialization::make_nvp(nvp.name(),iStr);
如果(iStr==nanCStr)nvp.value()=nan;
else nvp.value()=std::stod(iStr);
返回ia;
}
静态boost::archive::xml\u oarchive&
流(boost::archive::xml\u oarchive&oa、,
常量boost::序列化::nvp和nvp)
{
if(std::isnan(nvp.value())){
std::string nanStr=nanCStr;
oa首先,这不是boost archives特有的问题,它是iostream的一个功能,即文本流。您可以流式输出NaN值,但无法读回。我甚至不确定NaN将如何打印
如果您要“修补”boost库,那么可以在
boost/archive/basic_text_iprimitive.hpp
template< class IStream >
class basic_text_iprimitive
然后,您可以在阅读以下内容之前将其注入您的流:
is.imbue( infLocale )
(您也可以在第一次加载和读取XML时进行嵌入,如果只有一个库用于读取XML,那么就这样做,但是如果您在代码中的不同位置进行嵌入,那么这样做并不理想)
当然,为了确保一致性,您需要使用类似的区域设置来编写NAN。boost为此提供了一个nonfinite_num_put方面。您可以将其与nonfinite_num_get放在同一区域设置中,然后在创建XML文件句柄或专门化模板方法时将其嵌入到流中。需要一个小的复制程序。另外,yo你没有提到版本、存档类型等。在有效的情况下,在boost Trackers报告错误。我看了一下。一个简单的boost::optional就足够了吗?假设你不想区分NAN,只想在你的存档中将所有NAN存储为null。@CashCow-Heh。如果你不想存储它们,就不要存储它们。Optional是有效的,但它并不“足够”回答本问答的主题。(例如,为了避免头痛,停止进食一周就足够了。)如果你碰巧在boost property_树中有这些NAN,你就无法控制如何将其写入XML。它有效吗?@CashCow什么?不,没有。这就是重点。但是你的“解决方案”似乎只是“那就别那么做”。没有NaN并不能解决拥有NaN的问题。它只是否认问题。这个问题是问是否可以做到,答案是否定的。消除问题是一个解决办法。存在许多解决办法。这能解决问题吗?这当然是一个补丁,boost应该自己解决,但它可能很有效。@CashCow我们使用它指定特定类型应如何序列化是一种通用解决方案。@CashCow在上面的double
示例中,调用流函数,如stream(ar,boost::serialization::make_nvp(“double_var_name”,double_var_value))
。另外请注意,我们使用的是nanCStr
=“NaN”字符串表示南号。它可以被更改为<代码>“NANN”<代码>,使它更符合C++流。实际上我用我的解决方案解决了它。
template <>
class StreamSelector<double> {
public:
constexpr static double nan = std::numeric_limits<double>::quiet_NaN();
constexpr static const char* nanCStr = "nan";
static boost::archive::xml_iarchive&
stream(boost::archive::xml_iarchive& ia,
const boost::serialization::nvp<double>& nvp)
{
std::string iStr;
ia >> boost::serialization::make_nvp(nvp.name(), iStr);
if(iStr == nanCStr) nvp.value() = nan;
else nvp.value() = std::stod(iStr);
return ia;
}
static boost::archive::xml_oarchive&
stream(boost::archive::xml_oarchive& oa,
const boost::serialization::nvp<double>& nvp)
{
if(std::isnan(nvp.value())) {
std::string nanStr = nanCStr;
oa << boost::serialization::make_nvp(nvp.name(), nanStr);
}
else {
std::stringstream oStrm;
oStrm << std::setprecision(std::numeric_limits<double>::digits10 + 1)
<< nvp.value();
std::string oStr = oStrm.str();
oa << boost::serialization::make_nvp(nvp.name(), oStr);
}
return oa;
}
};
boost/archive/basic_text_iprimitive.hpp
template< class IStream >
class basic_text_iprimitive
template<class T>
void load(T & t)
namespace boost { namespace archive {
template<> template<>
void basic_text_iprimitive< std::istream >::load<double>( double& t )
{
// fix to handle NaNs
}
} } // close namespaces
std::locale infLocale( std::locale(), new boost::math::nonfinite_num_get<char>));
is.imbue( infLocale )