Boost Qi/X3 解析的类型安全

Type safety of Boost Qi/X3 parse

使用 Boost Spirit X3 考虑此代码(Boost Spirit Qi 在概念上同样适用):

  string command;
  string value;
  x3::parse(command.begin(), command.end(), "float:" >> x3::double_, value);

为什么这段代码在编译过程中没有产生任何错误? "float:" >> x3::double_ 解析器不应该具有类型 double 的属性,因此不接受 std::string 作为 parse 的第 4 个参数吗?

顺便说一句,我知道我可以做到:

string value;
auto assign = [](auto& ctx){value = _attr(ctx)};
x3::parse(command.begin(), command.end(), "float:" >> x3::double_[assign], value)

这会产生错误,但它比必要的更复杂。

作为最后的手段:是否有任何众所周知的 sscanf 类型安全的替代品(可能在 boost 中)?

这是因为将属性自动传播到容器中非常灵活。

std::string是一个容器。

也许如果我们做下面的实验会更有意义:

Live On Coliru

#include <boost/spirit/home/x3.hpp>
#include <iostream>
namespace x3 = boost::spirit::x3;

int main() {
    //std::string command = "f: hello world";
    std::string command = "f: 104 101 108 108 111 32 119 111 114 108 100";
    std::string value;
    x3::phrase_parse(
            command.begin(),
            command.end(),
            "f:" >> *x3::double_, x3::blank,
            value);

    std::cout << value << "\n";
}

如您所料,它会打印:

hello world

对于字符串,这似乎令人惊讶。如果目标是 std::vector<float> 就不足为奇了 - 但它需要的转化次数完全相同。

每个元素享受传播转换是公平的。如果你像这样解析 Ast 节点会怎样:

struct Operation {
     Operator op;
     std::vector<Expression> operands;
}

如果操作数没有从 UnaryFunctionCallStringLiteral 等隐式转换为 Expression,您会很讨厌

@tomasz-grobelny,使用 explicit_convert_parser_type 来自 here,以及 #defined REPRODUCE_SO_62986317,正确编译时 将 double 以外的任何内容作为属性传递时出错。

HTH,

拉里