【问题标题】:boost::spirit::karma using the alternatives operator (|) with conditionsboost::spirit::karma 使用带有条件的替代运算符 (|)
【发布时间】:2012-09-10 12:21:56
【问题描述】:

我正在尝试使用boost::spirit::karma 从我自己的名为Value 的类中生成一个字符串,但我遇到了这个问题。我试图将我的问题提取到一个简单的例子中。

我想从以下类的实例中生成一个带有业力的字符串:

class Value
{
public:

    enum ValueType
    {
        BoolType,
        NumericType
    };

    Value(bool b) : type_(BoolType), value_(b) {}
    Value(const double d) : type_(NumericType), value_(d) {};

    ValueType type() { return type_; }

    operator bool() { return boost::get<bool>(value_); }
    operator double() { return boost::get<double>(value_); }

private:
    ValueType type_;
    boost::variant<bool, double> value_;

};

在这里你可以看到我要做什么:

int main()
{
    using karma::bool_;
    using karma::double_;
    using karma::rule;
    using karma::eps;

    std::string generated;
    std::back_insert_iterator<std::string> sink(generated);

    rule<std::back_insert_iterator<std::string>, Value()> value_rule = bool_ | double_;

    Value bool_value = Value(true);
    Value double_value = Value(5.0);

    karma::generate(sink, value_rule, bool_value);
    std::cout << generated << "\n";

    generated.clear();

    karma::generate(sink, value_rule, double_value);
    std::cout << generated << "\n";

    return 0;
}

karma::generate() 的第一次调用工作正常,因为该值是一个布尔值,并且我的规则中的第一个生成器也“消耗”了一个布尔值。但是第二个 karma::generate()boost::bad_get 失败,因为 karma 试图吃布尔值并因此调用 Value::operator bool()

我的下一个想法是修改我的生成器规则并将eps() 生成器与条件一起使用,但在这里我卡住了:

value_rule = (eps( ... ) << bool_) | (eps( ... ) << double_);

我无法用 sth 填充 eps 生成器的括号。像这样(当然不行):

eps(value.type() == BoolType)

我试图进入boost::phoenix,但我的大脑似乎还没有准备好接受这样的事情。

请帮帮我!

这是我的完整示例(编译但不工作): main.cpp

【问题讨论】:

    标签: c++ boost-spirit boost-variant boost-spirit-karma


    【解决方案1】:

    想到的最简单的事情是:使用 value_ 变体(因为 Karma 非常支持变体)。

    在语义动作中使用 phoenix bind 会起作用:

    rule<std::back_insert_iterator<std::string>, Value()> value_rule;
    
    value_rule = (bool_ | double_) 
        [ _1 = phx::bind(&Value::value_, _val) ];
    

    虽然这需要公开value_(例如朋友)所以你可能更喜欢访问器方法。

    这是一个工作示例http://liveworkspace.org/code/22ab2093ad9bd3b03e55a7f3dde952f8

    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/phoenix.hpp>
    #include <boost/variant.hpp>
    
    #include <iostream>
    #include <string>
    
    namespace karma = boost::spirit::karma;
    namespace phx = boost::phoenix;
    
    class Value
    {
    public:
    
        enum ValueType
        {
            BoolType,
            NumericType
        };
    
        Value(bool b) : type_(BoolType), value_(b) {}
        Value(double d) : type_(NumericType), value_(d) {};
    
        ValueType type() { return type_; }
    
        operator bool()   { return boost::get<bool>(value_);   }
        operator double() { return boost::get<double>(value_); }
    
      private:
        ValueType type_;
    
        friend int main();
        boost::variant<bool, double> value_;
    };
    
    namespace karma = boost::spirit::karma;
    
    int main()
    {
        using namespace karma;
        std::string generated;
        std::back_insert_iterator<std::string> sink(generated);
    
        rule<std::back_insert_iterator<std::string>, Value()> value_rule;
    
        value_rule = (bool_ | double_) 
            [ _1 = phx::bind(&Value::value_, _val) ];
    
        Value bool_value = Value(true);
        Value double_value = Value(5.0);
    
        karma::generate(sink, value_rule, bool_value);
        std::cout << generated << "\n";
    
        generated.clear();
        karma::generate(sink, value_rule, double_value);
        std::cout << generated << "\n";
    
        return 0;
    }
    

    输出

    true
    5.0
    

    题外话:我可以建议标记转换运算符 explicit(至少),以避免令人讨厌的意外吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多