Функции шаблона-помощника или перегруженные операторы (например, & lt; & amp;) могут использоваться для вызова селектора потоков - специализированного статического шаблона. Специалисты селектора потоков затем выбирают правильные функции потоковой передачи, основанные на сериализованном типе:
template
boost::archive::xml_iarchive&
stream(boost::archive::xml_iarchive& ia,
const boost::serialization::nvp& nvp)
{
return StreamSelector::stream(ia, nvp);
}
template
boost::archive::xml_oarchive&
stream(boost::archive::xml_oarchive& oa,
const boost::serialization::nvp& nvp)
{
return StreamSelector::stream(oa, nvp);
}
Стандартный класс статического шаблона селектора потоков может быть определен для любого типа, поддерживаемого boost::archive::xml_iarchive
, следующим образом:
template
class StreamSelector {
public:
static boost::archive::xml_iarchive&
stream(boost::archive::xml_iarchive& ia,
const boost::serialization::nvp& nvp)
{
ia.operator >>(nvp);
return ia;
}
static boost::archive::xml_oarchive&
stream(boost::archive::xml_oarchive& oa,
const boost::serialization::nvp& nvp)
{
oa.operator <<(nvp);
return oa;
}
};
Тогда селектор потоков может быть специализирован для double
для обработки NaN
или для вывода значений с плавающей запятой в более удобочитаемом формате в архив:
template <>
class StreamSelector {
public:
constexpr static double nan = std::numeric_limits::quiet_NaN();
constexpr static const char* nanCStr = "nan";
static boost::archive::xml_iarchive&
stream(boost::archive::xml_iarchive& ia,
const boost::serialization::nvp& 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& 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::digits10 + 1)
<< nvp.value();
std::string oStr = oStrm.str();
oa << boost::serialization::make_nvp(nvp.name(), oStr);
}
return oa;
}
};
Другое аналогичные функции селектора потока могут быть добавлены для обработки большего количества типов (например, float, long double) и более специальных случаев, таких как бесконечности.
Live demo: Open In Coliru