gpt4 book ai didi

c++ - 如何在使用 boost 进行 QI 解析期间舍入一个数字?

转载 作者:行者123 更新时间:2023-12-01 14:47:11 24 4
gpt4 key购买 nike

用一个简单的 Boost qi 语法,我怎样才能让它四舍五入我的数字?
这是解析器:

factor =
float_ [_val = _1]
| ('-' >> factor [_val = -_1])
| ('+' >> factor [_val = _1])
;
这可以解析一个浮点数,也可以是负数。
我想对浮点数进行四舍五入,所以我会在语法中添加这样的内容:
|   ('~' >> factor              [_val = round(_1)])
但这会导致编译时错误:

no type named ‘__type’ in ‘struct __gnu_cxx::__enable_if<false, double>’


这个错误对我来说信息量不大,你能帮忙吗?我希望能够舍入一个数字,即:
~1.8 -> 2
~1.2 -> 1
注意:我正在解析 phrase_parse .

最佳答案

语义 Action 需要 Phoenix Actors,这是延迟函数。
选项:

  • 适配宏 https://www.boost.org/doc/libs/1_73_0/libs/phoenix/doc/html/phoenix/modules/function/adapting_functions.html
  • phoenix::function<>
  • phoenix::bind
  • 自己写,详情见 https://www.boost.org/doc/libs/1_68_0/libs/spirit/doc/html/spirit/qi/tutorials/semantic_actions.html#spirit.qi.tutorials.semantic_actions.examples_of_semantic_actions

  • 简化试验台
    只解析一个数字:
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    namespace qi = boost::spirit::qi;

    int main() {
    std::string s = "1.75";

    double v;
    if (qi::parse(begin(s), end(s), qi::double_, v)) {
    std::cout << "Parsed: " << v << "\n";
    }
    }
    打印 Live On Coliru :
    Parsed: 1.75
    适应
    使用宏:
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <cmath>
    namespace qi = boost::spirit::qi;

    int main() {
    std::string s = "1.75";

    double v;
    if (qi::parse(begin(s), end(s), qi::double_, v)) {
    std::cout << "Parsed: " << v << "\n";
    std::cout << "Rounded: " << round(v) << "\n";
    }
    }
    打印 Live On Coliru :
    Parsed: 2
    function<>您可以在此处对签名进行硬编码:
    boost::phoenix::function<double(*)(double)> round_(::round);
    然而,真正的力量来自多态可调用对象:
    struct round_f {
    template <typename T> auto operator()(T const& v) const {
    using std::round; // activate ADL
    return round(v);
    }
    };
    boost::phoenix::function<round_f> round_{};
    现在您可以使用 round_具有自由函数重载的任何类型的actor round兼容的过载。如果明天你决定解析 long double 会很方便, floatboost::multiprecision::cpp_dec_float .
    看到它 Live On Coliru
    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <cmath>
    namespace qi = boost::spirit::qi;

    struct round_f {
    template <typename T> auto operator()(T const& v) const {
    using std::round; // activate ADL
    return round(v);
    }
    };
    boost::phoenix::function<round_f> round_{};

    int main() {
    std::string s = "1.75";

    double v;
    using namespace qi::labels;
    if (qi::parse(begin(s), end(s), qi::double_ [ _val = round_(_1) ], v)) {
    std::cout << "Parsed: " << v << "\n";
    }
    }
    打印
    Parsed: 2
    使用 phoenix::bind作为较低级别的构建 block ,您可以绑定(bind)未包装的可调用对象:
    if (qi::parse(begin(s), end(s), qi::double_ 
    [ _val = phoenix::bind(round_f{}, _1) ], v))
    {
    std::cout << "Parsed: " << v << "\n";
    }
    如果你不介意丑:
    if (qi::parse(begin(s), end(s), qi::double_ 
    [ _val = phoenix::bind(static_cast<double(&)(double)>(std::round), _1) ], v))
    {
    std::cout << "Parsed: " << v << "\n";
    }
    参见 Live On Coliru

    关于c++ - 如何在使用 boost 进行 QI 解析期间舍入一个数字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63193696/

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