gpt4 book ai didi

c++ - 如何在 qi 符号表中使用 std::function

转载 作者:行者123 更新时间:2023-12-02 10:30:56 25 4
gpt4 key购买 nike

我有以下代码。此代码将解析两个 int 并将比较结果作为 bool 返回。
为了比较,我使用 qi::symbol 表。但是,不幸的是,它不能编译。知道出了什么问题吗?

#include <boost/spirit/include/qi.hpp>
int main(sint32 argc, char **argv)
{
boost::spirit::qi::symbols<char, std::function<bool(int, int)>> sym;
sym.add
("==", [](int v1, int v2) {return v1 == v2; })
("!=", [](int v1, int v2) {return v1 != v2; });
bool result;
std::string s("1==2");
namespace qi = boost::spirit::qi;
qi::phrase_parse(s.begin(), s.end(), (qi::int_ >> sym >> qi::int_)[qi::_val = boost::bind(qi::_2, qi::_1, qi::_3)], qi::space, result);
}

最佳答案

首先,不要使用boost::bind在语义 Action 中。

语义 Action 需要是 Phoenix Actors。换句话说,延迟或惰性函数对象。

获得它的方法通常是使用 boost::phoenix::bind ,但在这种情况下你输了:绑定(bind)不需要占位符,也不知道如何绑定(bind)到它。

相反,让符号表公开延迟函数。但是你需要高级魔法来保护内部绑定(bind)免受外部绑定(bind):Post callbacks to a task queue using boost::bind

相反,我建议在自定义惰性操作中进行整个评估:

auto bin_eval = [](auto const& lhs, auto const& op, auto const& rhs) {
return op(lhs, rhs);
};

进而
   (qi::int_ >> sym >> qi::int_)
[qi::_val = px::bind(bin_eval, _1, _2, _3)],

然而,这还不是全部。您的示例可能过于简单,因为它甚至无法使用正确的语义操作进行编译。相反,您需要抑制属性传播,这仅在您将语义操作添加到规则时才会发生:

Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iomanip>

namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;

int main() {
qi::symbols<char, std::function<bool(int, int)>> sym;
sym.add
("==", [](int v1, int v2) {return v1 == v2; })
("!=", [](int v1, int v2) {return v1 != v2; });

using namespace qi::labels;
bool result;
auto bin_eval = [](auto const& lhs, auto const& op, auto const& rhs) {
return op(lhs, rhs);
};

qi::rule<std::string::const_iterator, bool(), qi::space_type> rule;
rule = (qi::int_ >> sym >> qi::int_)
[qi::_val = px::bind(bin_eval, _1, _2, _3)];

for (std::string const s : {"1==2", "1!=2" }) {
std::cout << std::quoted(s) << " -> ";

if (qi::phrase_parse(s.begin(), s.end(), rule, qi::space, result)) {
std::cout << "result: " << std::boolalpha << result << "\n";
} else {
std::cout << "parse failed\n";
}
}
}

打印
"1==2" -> result: false
"1!=2" -> result: true

更漂亮?

对于奖励积分, boost 到适当的凤凰功能:
struct bin_eval_t {
template <typename T, typename U, typename V>
auto operator()(T const& lhs, U const& op, V const& rhs) const {
return op(lhs, rhs);
}
};

// ...
px::function<bin_eval_t> bin_eval;

// ...
rule = (qi::int_ >> sym >> qi::int_)
[qi::_val = bin_eval(_1, _2, _3)];

更简单?

您可以用 std 函数替换 lambda:
sym.add
("==", std::equal_to<>{})
("!=", std::not_equal_to<>{});

或者如果你没有 c++14
sym.add
("==", std::equal_to<int>{})
("!=", std::not_equal_to<int>{});

多得多?

如果您想要异构评估(不仅仅是 bool 谓词)、一元运算符、优先级、关联性,请查看我在此站点上制作的一些示例。

通常他们将评估阶段与解析阶段分开:
  • 这是最新最完整的https://github.com/sehe/qi-extended-parser-evaluator (为 this question 制作,详细讨论 in this chat
  • 许多更简单的例子on this site

  • 但是,如果您愿意,您确实可以将解析与评估结合起来。在这种情况下,将所有内容简化为直接在语义操作中是有意义的:

    Live On Coliru
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <iomanip>

    namespace qi = boost::spirit::qi;

    int main() {
    using namespace qi::labels;

    for (std::string const s : {"1==2", "1!=2" }) {
    std::cout << std::quoted(s) << " -> ";

    bool result;
    if (qi::phrase_parse(s.begin(), s.end(),
    qi::int_ >> (
    "==" >> qi::int_ [ _val = (_val == _1) ]
    | "!=" >> qi::int_ [ _val = (_val != _1) ]
    ),
    qi::space,
    result))
    {
    std::cout << "result: " << std::boolalpha << result << "\n";
    } else {
    std::cout << "parse failed\n";
    }
    }
    }

    打印
    "1==2" -> result: false
    "1!=2" -> result: true

    关于c++ - 如何在 qi 符号表中使用 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62304856/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com