如何让Boost Units中的缩放单位可转换为字符串?
解决Boost.Units自定义瓦特小时单位的打印错误
问题描述
需要定义瓦特小时(Wh)单位,它与焦耳(J)维度相同,转换因子为3600,初始采用make_scaled_unit定义缩放单位:
namespace si = boost::units::si; typedef boost::units::make_scaled_unit<si::energy, boost::units::scale<3600, boost::units::static_rational<1>>>::type watt_hour_unit; BOOST_UNITS_STATIC_CONSTANT(watt_hours, watt_hour_unit); typedef boost::units::quantity<watt_hour_unit> watt_hour;
该单位可正常转换为SI能量单位并打印:
watt_hour const energy_whs = 1.0 * watt_hours; boost::units::quantity<boost::units::si::energy, double> energy_conv(energy_whs); std::cout << energy_conv << std::endl; // 输出"3600 J"
但直接打印该缩放单位时触发编译错误:
std::cout << energy_whs << std::endl; // 期望输出"1 Wh"
错误信息:
[...]/usr/include/boost/units/io.hpp:327:39: error: ‘symbol’ is not a member of ‘boost::units::list<boost::units::scale_list_dim<boost::units::scale<3600, boost::units::static_rational<1> > >, boost::units::dimensionless_type>::item’ {aka ‘boost::units::scale_list_dim<boost::units::scale<3600, boost::units::static_rational<1> > >’} 327 | str += Begin::item::symbol(); | ~~~~~~~~~~~~~~~~~~~^~ [...]/usr/include/boost/units/io.hpp:393:37: error: ‘name’ is not a member of ‘boost::units::list<boost::units::scale_list_dim<boost::units::scale<3600, boost::units::static_rational<1> > >, boost::units::dimensionless_type>::item’ {aka ‘boost::units::scale_list_dim<boost::units::scale<3600, boost::units::static_rational<1> > >’} 393 | str += Begin::item::name(); | ~~~~~~~~~~~~~~~~~^~
尝试定义name_string和symbol_string函数后,第二个错误消失,但第一个错误仍存在:
namespace boost { namespace units { std::string name_string(const watt_hour_unit&) { return "Watt hours"; } std::string symbol_string(const watt_hour_unit&) { return "Wh"; } } }
解决方案
问题出在make_scaled_unit生成的单位包含scale_list_dim类型,Boost.Units的IO系统无法直接处理该类型的符号输出。正确做法是直接定义SI系统下的能量派生单位,显式注册转换因子和IO符号:
#include <boost/units/systems/si/energy.hpp> #include <boost/units/conversion.hpp> #include <boost/units/io.hpp> #include <iostream> namespace si = boost::units::si; // 定义瓦特小时单位,属于SI系统的能量维度单位 typedef boost::units::unit<boost::units::energy_dimension, boost::units::si::system> watt_hour_unit; BOOST_UNITS_STATIC_CONSTANT(watt_hours, watt_hour_unit); typedef boost::units::quantity<watt_hour_unit> watt_hour; // 注册Wh和J的双向转换因子 BOOST_UNITS_DEFINE_CONVERSION_FACTOR(watt_hour_unit, si::energy, double, 3600.0); BOOST_UNITS_DEFINE_CONVERSION_FACTOR(si::energy, watt_hour_unit, double, 1.0 / 3600.0); // 注册单位的名称和符号,供IO系统使用 namespace boost { namespace units { std::string name_string(const watt_hour_unit&) { return "Watt hours"; } std::string symbol_string(const watt_hour_unit&) { return "Wh"; } }} int main() { watt_hour const energy_whs = 1.0 * watt_hours; std::cout << energy_whs << std::endl; // 输出"1 Wh" // 转换为SI单位验证 boost::units::quantity<si::energy> energy_conv(energy_whs); std::cout << energy_conv << std::endl; // 输出"3600 J" return 0; }
原理说明
- 直接基于SI系统的能量维度定义单位,避免
make_scaled_unit带来的scale_list_dim兼容性问题 - 通过
BOOST_UNITS_DEFINE_CONVERSION_FACTOR显式注册单位间的转换关系,保证数值转换正确 - 注册
name_string和symbol_string为IO系统提供单位的可读名称和符号
内容的提问来源于stack exchange,提问作者nbwbx
相关产品推荐
相关产品推荐

