You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 10:33:30