提升精神 QI:在元组上自动规则演绎,在替代函数中带有序列
Boost Spirit QI : Auto-rule deduction on a tuple with a sequence inside an alternative function
我正在尝试使用自动规则推导来分配给三个元素的元组。第二种类型是字符串,第三种是字符串向量(第一个参数的类型对于此示例不是那么重要(。
我正在努力理解为什么以下代码无法编译。
#include <boost/fusion/include/std_tuple.hpp>
#include <boost/spirit/include/qi.hpp>
using namespace boost::spirit::qi;
using iterator = std::string::const_iterator;
void qi_compile_test1()
{
rule<iterator, std::string(), space_type> r_s1, r_s2;
rule<iterator, std::vector<std::string>(), space_type> r_vec_s1, r_vec_s2;
rule<iterator, std::tuple<float, std::string, std::vector<std::string>>(), space_type> r;
r %=
float_ >
((r_s1 > r_vec_s1) |
(r_s2 > r_vec_s2));
}
错误如下(在字符串作为第二个参数的字符串上调用函数插入(:
/opt/wandbox/boost-1.68.0/clang-6.0.1/include/boost/spirit/home/support/container.hpp:292:15: error: no matching member function for call to 'insert'
c.insert(c.end(), val);
~~^~~~~~
/opt/wandbox/boost-1.68.0/clang-6.0.1/include/boost/spirit/home/support/container.hpp:354:51: note: in instantiation of member function 'boost::spirit::traits::push_back_container<std::__1::basic_string<char>, std::__1::basic_string<char>, void>::call' requested here
return push_back_container<Container, T>::call(c, val);
简而言之,定义了以下规则:
A > ((B > C) | (B > C))
我怀疑错误来自以下事实:C 与 B <向量相同,>可以恢复为:
A > ((B > vector<B>) | (B > vector<B))
根据复合属性规则,我假设错误来自以下解决方案:
A > (vector<B> | vector<B>) a : A, b: vector<A> --> (a > b): vector<A>
A > vector<B> a : A, b: A --> (a | b): A
由于合成属性是三个元素的元组,我希望自动规则能够按顺序保留三种不同类型的类型:
A > ((B > vector<B>) | (B > vector<B))
A > (B > vector<B>) a : A, b: A --> (a | b): A
我不明白的是,以下代码编译:
void qi_compile_test2()
{
rule<iterator, int(), space_type> r_int1, r_int2;
rule<iterator, std::vector<int>(), space_type> r_vec_int1, r_vec_int2;
rule<iterator, std::tuple<float, int, std::vector<int>>(), space_type> r;
r %=
float_ >
((r_int1 > r_vec_int1) |
(r_int2 > r_vec_int2));
}
唯一的区别是将类型 B 从 std::string 替换为 int。我想这简化了事情,因为 std::string 是一个容器,但不是"int"类型。在这种情况下,我不明白这种变化会导致什么。
此外,通过收回第一个公式并删除元组的第一个参数,我们能够编译(仍然保留替代函数和涉及字符串的相同序列顺序(。
void qi_compile_test3()
{
rule<iterator, std::string(), space_type> r_s1, r_s2;
rule<iterator, std::vector<std::string>(), space_type> r_vec_s1, r_vec_s2;
rule<iterator, std::tuple<std::string, std::vector<std::string>>(), space_type> r;
r %=
((r_s1 > r_vec_s1) |
(r_s2 > r_vec_s2));
}
我很想将等式简化为以下内容,但我认为如果不使用 lambda 的语义操作来展平元组,就无法完成。
void qi_compile_test4()
{
rule<iterator, std::tuple<std::string, std::vector<std::string>>(), space_type> r_p1, r_p2;
rule<iterator, std::tuple<float, std::string, std::vector<std::string>>(), space_type> r;
r %=
float_ >
(r_p1 | r_p2 );
}
可以在此处编译此代码: https://wandbox.org/permlink/iJLRz1TKMK2pWMVb
我在这里要完成的是能够让元组的最后两个元素相互依赖。我想保留两个元素的顺序,但用替代函数分开。删除替代函数并仅保留两个语句中的一个会编译但删除所需的逻辑。
我想避免使用语义操作,因为在我的真实情况下,我的元组包含更多的元素(通过融合枚举的结构(,因为一旦我使用语义操作在元组中分配适当的字段,我就必须分配它们中的每一个。有人对如何解决这个问题有任何建议吗?
谢谢
不幸的是,Spirit(Qi 和 X3(只连接序列解析器1的元组。虽然期待解析器的平面表示似乎是很自然的,但 Spirit 并没有那么深入。它的行为非常简单2,修复将需要对属性操作进行大量重构。
- 但是,一元是透明的,因此
float_ >> lexeme[int_ >> char_]
结果tuple<float, int, char>
。
#include <boost/spirit/home/qi.hpp>
#include <boost/core/demangle.hpp>
#include <typeinfo>
namespace qi = boost::spirit::qi;
template <typename Iterator = char const*, typename Context = qi::unused_type, typename Parser>
void print_parser_attr_type(Parser const& p)
{
using attr_type = typename decltype(boost::spirit::compile<qi::domain>(p))::template attribute<Context, Iterator>::type;
std::cout << boost::core::demangle(typeid(attr_type).name()) << 'n';
}
int main()
{
print_parser_attr_type(qi::float_ >> ((qi::int_ >> qi::char_) | (qi::int_ >> qi::char_)));
}
输出:
boost::fusion::vector<float, boost::fusion::vector<int, char> >
- 您可能会
- 感到惊讶,
float_ >> no_case[int_ >> char_]
可以完美地解析为tuple<float, tuple<int, char>>
但float_ >> (int_ >> char_)
不会。
- 使用显式模板参数列表和 [temp.arg.explicit]/3 的函数调用的演绎失败
- 提升精神 QI:在元组上自动规则演绎,在替代函数中带有序列
- 如何使用模板化构造函数定义演绎指南?
- 演绎指南和具有可变参数模板构造函数的可变参数类模板 - 参数包长度不匹配
- 可变参数模板构造函数的演绎指南失败
- 模板作为函数模板的参数 - 演绎失败
- c++ 11使用std::函数进行类型演绎
- 成员函数指针的模板实参演绎
- 错误:没有匹配的函数调用[…]注意:模板参数演绎/替换失败
- c++如何在无法进行类型演绎时调用模板化构造函数
- 函数模板中返回类型的模板实参演绎
- 调用模板函数时的模板演绎
- 类型演绎模板函数c++
- 用演绎的类型公开类成员函数
- 括号初始化列表和函数模板类型演绎顺序
- 在模板演绎中保持函数指针形参的完整类型
- 用const实参重载实参演绎的c++模板函数
- 定义任何成员函数指针的别名中的模板实参演绎
- 在类型演绎之后,函数模板中的替换顺序是否有任何保证
- c++中转换函数模板实参演绎的含义