【问题标题】:What header files should i include in order to use limit_d directive in boost spirit?为了在提升精神中使用 limit_d 指令,我应该包含哪些头文件?
【发布时间】:2015-08-19 15:40:07
【问题描述】:

我是使用boost spirit的初学者。

我想要做的只是解析一个具有以下格式的时间的文本:

HH:MM::SS

这很容易通过使用以下规则(增强文档)

uint_parser<int, 10, 2, 2> uint2_p;

r = lexeme_d
    [
        boost::spirit::limit_d(0u, 23u)[uint2_p] >> ':' 
        >>  boost::spirit::limit_d(0u, 59u)[uint2_p] >> ':' 
        >>  boost::spirit::limit_d(0u, 59u)[uint2_p]           
    ];

问题是我收到一个编译器错误,指出 limit_d 不是 boost spirit 命名空间的成员,即使 limit_d 指令位于以下标头中的 boost::spirit 命名空间下:

boost/spirit/home/classic/core/composite/directives.hpp

我已经包含了这个标题。

所以我很困惑我应该包含哪个标头才能编译代码(我使用的是 VS2013)

附:我的代码在没有limit_d 指令的情况下正常工作,所以问题肯定是由limit_d 引起的。

【问题讨论】:

  • 来自this 示例,他们在没有限定名称的情况下调用它。
  • ...如果您发布了MCVE,我可以查看它与我的工作生产代码有何不同,并在答案中写下差异。由于您没有费心编写 MCVE,我也不想将my 代码变成MCVE。你明白这是怎么回事了吗?
  • 感谢@NathanOliver 纠正错误。我知道调用它的示例没有限定名称,但是我已经尝试过了,编译错误已更改为“'limit_d':未找到标识符”

标签: c++ parsing boost-spirit


【解决方案1】:

您是supposed,可以使用&lt;boost/spirit/include/...&gt; 中的标头,以便Boost 可以在不影响客户端代码的情况下改变其内部结构。

include &lt;boost/spirit/include/classic_directives.hpp&gt; 只是 使用的一个包装器,因此除了忽略一层抽象之外,您的标头没有任何问题。

真正的问题是你使用的命名空间 -- boost::spirit -- 与你应该使用的那个 -- @ 987654326@.

IIRC,当新的 Spirit v2 API 出现并试图修复 Spirit "Header Hell" 时,他们将之前的 boost::spirit 转换为 boost::spirit::classic 几个版本。

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

namespace bspirit = boost::spirit::classic;

int main()
{
    bspirit::limit_d( 0u, 23u );
}

如果您不害怕更高的编译时间并且不想弄清楚要使用哪个标头确切,您当然可以简单地#include &lt;boost/spirit/include/classic.hpp&gt; 并完成它。 ;-)

【讨论】:

  • Orrrrr 只是使用在过去十年中某个地方支持的库版本 :) “几个版本之前”有点用词不当。它认为是 20 年前的版本。
  • @sehe:如果我没有采取严厉措施,就我个人而言,我的公司仍然坚持我们的一款产品使用 ICU 3.6 和 Boost 1.34.1,因为“这就是我们测试的”。 :-D
【解决方案2】:

使用@DevSolar 发布的答案,我可以看到limit_d,但这会引入另一个编译错误,说明我们不能使用

boost::spirit::qi::uint_parser<int, 10, 2, 2> uint2_p;

limit_d 所以我把它改成了

boost::spirit::classic::uint_parser<uint16, 10, 2, 2> uint2_p;

因此,时间解析器规则如下:

boost::spirit::classic::uint_parser<uint16, 10, 2, 2>           uint2_p;
boost::spirit::qi::rule<std::string::const_iterator, Time(), qi::space> Time_;

Time_ = lexeme_d
    [
            boost::spirit::classic::limit_d(0u, 23u)[uint2_p] >> ':'
        >>  boost::spirit::classic::limit_d(0u, 59u)[uint2_p] >> ':'
        >>  boost::spirit::classic::limit_d(0u, 59u)[uint2_p]
    ];

此代码的问题是我们不能将limit_dBoost::Spirit::QI 一起使用,因为您已经注意到来自 QI 命名空间的规则。

所以我搜索了与 Spirit 2.x 兼容的 limit_d 等效项

here 所述,在 Spirit 2.x 中没有 limit_d 的等价物,而是您必须使用语义操作,这可以解决我的问题。

所以工作代码应该是这样的:

    namespace qi = boost::spirit::qi;
    struct Time
    {
        unsigned Hour;
        unsigned Minute;
        unsigned Second;
    };

    boost::spirit::qi::rule<std::string::const_iterator, Time(), qi::space> Time_;

    Time_ = lexeme_d
        [
                    qi::uint_[qi::_pass = (0 <= qi::_1 && qi::_1 <= 23)] >> ':'
                >>  qi::uint_[qi::_pass = (0 <= qi::_1 && qi::_1 <= 59)] >> ':'
                >>  qi::uint_[qi::_pass = (0 <= qi::_1 && qi::_1 <= 59)]
        ];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多