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

使用Boost.Spirit解析RFC3339 Duration遇编译错误求助

解决Boost.Spirit解析RFC3339 Duration的编译错误

问题背景

使用Boost.Spirit解析RFC3339定义的Duration(已移除周支持),定义了包含年、月、日、时、分、秒的Duration结构体并通过BOOST_FUSION_ADAPT_STRUCT适配,但编译时出现如下错误:

/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching function for call to 'Duration::Duration(const int&)'
153 | attr = static_cast(val);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~

错误根源是m_start规则的属性无法匹配Duration结构体对应的六整数序列,因不确定规则实际属性类型而使用了auto和copy指令,需要调整语法或采用其他解决方法。

解决方法

1. 显式指定规则属性类型

不要依赖auto推导规则属性,直接将规则的属性类型指定为Duration或对应的融合序列类型,让Spirit明确知道要绑定的目标类型:

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

struct Duration {
    int years = 0;
    int months = 0;
    int days = 0;
    int hours = 0;
    int minutes = 0;
    int seconds = 0;
};

BOOST_FUSION_ADAPT_STRUCT(Duration, years, months, days, hours, minutes, seconds)

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct DurationGrammar : qi::grammar<Iterator, Duration()> {
    DurationGrammar() : DurationGrammar::base_type(m_start) {
        // 后续规则定义
    }

    qi::rule<Iterator, Duration()> m_start;
};

2. 对齐语法规则与结构体成员顺序

确保语法规则生成的属性序列顺序,和BOOST_FUSION_ADAPT_STRUCT中声明的结构体成员顺序完全一致。对于RFC3339中可选的时间分量,需要用qi::attr(0)为缺失的分量填充默认值,保证属性序列始终是6个int值:

m_start = qi::lit("P")
    >> (qi::int_ >> 'Y' | qi::attr(0))
    >> (qi::int_ >> 'M' | qi::attr(0))
    >> (qi::int_ >> 'D' | qi::attr(0))
    >> -(qi::lit("T")
        >> (qi::int_ >> 'H' | qi::attr(0))
        >> (qi::int_ >> 'M' | qi::attr(0))
        >> (qi::int_ >> 'S' | qi::attr(0))
    );

这里通过| qi::attr(0)处理可选分量,确保每个位置都能输出int值,匹配结构体的融合属性序列。

3. 直接绑定结构体成员赋值(可选)

如果需要更灵活地控制赋值逻辑,可以使用Boost.Phoenix直接绑定结构体成员,避免属性序列不匹配的问题:

#include <boost/spirit/include/phoenix.hpp>

namespace phx = boost::phoenix;

// 在语法构造函数中
m_start = qi::lit("P")
    >> -(qi::int_ >> 'Y')[phx::bind(&Duration::years, qi::_val) = qi::_1]
    >> -(qi::int_ >> 'M')[phx::bind(&Duration::months, qi::_val) = qi::_1]
    >> -(qi::int_ >> 'D')[phx::bind(&Duration::days, qi::_val) = qi::_1]
    >> -(qi::lit("T")
        >> -(qi::int_ >> 'H')[phx::bind(&Duration::hours, qi::_val) = qi::_1]
        >> -(qi::int_ >> 'M')[phx::bind(&Duration::minutes, qi::_val) = qi::_1]
        >> -(qi::int_ >> 'S')[phx::bind(&Duration::seconds, qi::_val) = qi::_1]
    );

这种方式不需要严格的属性序列匹配,直接为每个存在的分量赋值,缺失的分量保持结构体的默认值(需确保结构体成员有默认初始化)。

4. 保证结构体有默认构造能力

Spirit解析时需要先默认构造Duration对象再逐步赋值,因此结构体必须支持默认构造:

  • 如果没有显式定义任何构造函数,编译器会自动生成默认构造函数;
  • 如果有显式构造函数,需要手动添加默认构造函数(如Duration() = default;)。

内容的提问来源于stack exchange,提问作者Aaron Wright

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 07:43:28