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
是一个容器。
也许如果我们做下面的实验会更有意义:
#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;
}
如果操作数没有从 Unary
、FunctionCall
、StringLiteral
等隐式转换为 Expression
,您会很讨厌
@tomasz-grobelny,使用 explicit_convert_parser_type
来自
here,以及 #defined REPRODUCE_SO_62986317
,正确编译时
将 double
以外的任何内容作为属性传递时出错。
HTH,
拉里
使用 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
是一个容器。
也许如果我们做下面的实验会更有意义:
#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;
}
如果操作数没有从 Unary
、FunctionCall
、StringLiteral
等隐式转换为 Expression
,您会很讨厌
@tomasz-grobelny,使用 explicit_convert_parser_type
来自
here,以及 #defined REPRODUCE_SO_62986317
,正确编译时
将 double
以外的任何内容作为属性传递时出错。
HTH,
拉里