首页 > 解决方案 > Boost Qi/X3 解析的类型安全

问题描述

考虑使用 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吗?

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

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

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

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

标签: c++boostboost-spiritboost-spirit-qiboost-spirit-x3

解决方案


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

并且std::string是一个容器。

也许如果我们做以下实验,它会更有意义:

住在科利鲁

#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;
}

如果操作数没有隐式转换为Expressionfrom Unary,您会讨厌FunctionCallStringLiteral等等。


推荐阅读