2

Valueusingという独自のクラスから文字列を生成しようとしていますがboost::spirit::karma、これで行き詰まりました。私の問題を簡単な例に抽出しようとしました。

次のクラスのインスタンスから、カルマを使用して文字列を生成したいと考えています。

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()値が bool であり、ルールの最初のジェネレーターも bool を「消費」するため、最初の呼び出しは正常に機能します。しかし、カルマが bool を食べようとして、それゆえ を呼び出すため、2 番目karma::generate()は失敗します。boost::bad_getValue::operator bool()

次に考えたのは、ジェネレーター ルールを変更し、ジェネレーターeps()を条件と共に使用することでしたが、ここで行き詰まりました。

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

eps ジェネレーターの括弧を sth で埋めることができません。このように(もちろん動作しません):

eps(value.type() == BoolType)

入ってみましたboost::phoenixが、私の脳はこのようなことに対して準備ができていないようです.

私を助けてください!

これが私の完全な例です(コンパイルしていますが動作していません): main.cpp

4

1 に答える 1

3

頭に浮かぶ最も簡単なことは、value_バリアントを使用することです (バリアントは Karma によって非常によくサポートされているため)。

セマンティック アクション内でフェニックス バインドを使用すると、次のように動作します。

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

于 2012-09-11T00:13:32.847 に答える