1

私の問題を以下の (おそらく最小ではない) サンプル アプリケーションに要約しました。サンプルは汎用の JSON パーサーです。ただし、2 つの問題があります。1. 他のオプションがどれもパスしない場合、bool_ がバリアント リストのアウトプッターである場合、常に true または false を出力します。それが最後のものでない場合、それ以降は事実上使用されません。理由がわかりません。2. 入力が文字列の場合、バリアントから文字列ハンドラが起動されることはありません。バリアントの外で使用すると、発火します。

サンプル コードでは、単純化された文字列出力が karma::string になっていますが、それでもエラーが発生します。ここで学んだことを実際のアプリケーションに戻すと、文字列出力は C スタイルのエスケープ文字列になるため、karma::string でのみ機能するものは役に立ちません。

Output of a boost::variant type using boost::spirit::karmaおよびboost::spirit::karma 引用符で囲まれた文字列の出力 を既に読んだ(そして読み直した)が、どちらも私のケースに適切に適用できない(つまり、結局のところ答えがわかりません) または、より複雑な例では機能しません。また、mini_xml のサンプル コードにも精通しています。

私が間違っていることについて何か提案はありますか? そして、なぜ私がやっていることは間違っていて、修正は正しいのですか?

すべてのヘルプは本当に感謝しています。

#include <boost/variant/recursive_variant.hpp>
#include <string>
#include <vector>

namespace lloyd
{
namespace json
{

struct null
{
    bool operator==(const null& cmp) {return true; }
};

struct element;

typedef boost::make_recursive_variant<null, bool, long, double, std::string, std::vector<element>, std::vector<boost::recursive_variant_> >::type value;

struct element
{
    std::string name;
    json::value value;
    inline element(const element& src): name(src.name), value(src.value) {}
    inline element(const std::string& name, const json::value& value): name(name), value(value) {}
    inline element() {}
};

typedef std::vector<element> object;

}
}

#include <boost/fusion/adapted.hpp>

BOOST_FUSION_ADAPT_STRUCT(
    lloyd::json::element,
    (std::string, name)
    (lloyd::json::value, value)
)

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/karma_auto.hpp>

#include <boost/spirit/include/phoenix.hpp>

namespace lloyd { namespace json { namespace karma {

template <typename OutputIterator>
struct json_object_out_generator
    : boost::spirit::karma::grammar<OutputIterator, json::object(bool, unsigned, unsigned) >
{
    //  JSON Output Grammars
    boost::spirit::karma::rule<OutputIterator, std::vector<json::value>(bool, unsigned, unsigned) > array_rule;
    boost::spirit::karma::rule<OutputIterator, json::null(bool, unsigned, unsigned) > null_rule;
    boost::spirit::karma::rule<OutputIterator, json::value(bool, unsigned, unsigned) > value_rule;
    boost::spirit::karma::rule<OutputIterator, json::element(bool, unsigned, unsigned) > elem_rule;
    boost::spirit::karma::rule<OutputIterator, json::object(bool, unsigned, unsigned) > obj_rule;

    json_object_out_generator() : json_object_out_generator::base_type(obj_rule)
    {
        using boost::spirit::lit;
        using boost::spirit::_r1;
        using boost::spirit::_r2;
        using boost::spirit::_r3;

        namespace karma=boost::spirit::karma;

        null_rule %= karma::eps << boost::spirit::karma::lit("null");
        array_rule %= lit("[") << -(value_rule(_r1, _r2, _r3) % lit(",") ) << "]";
        value_rule %= ( null_rule(_r1, _r2, _r3) | karma::string | karma::long_ | karma::double_ | obj_rule(_r1, _r2, _r3) | array_rule(_r1, _r2, _r3) | karma::bool_);
        elem_rule %= boost::spirit::karma::string << ":" << -value_rule(_r1, _r2+1, _r3);
        obj_rule %= boost::spirit::lit("{")
            << -boost::spirit::buffer[( elem_rule(_r1, _r2+1, _r3)  % ',' ) ]
            << "}";

    }
};

}}}

#include <vector>
#include <sstream>
#include <iomanip>

#include <boost/assign/list_of.hpp>

#include <boost/assign/std/vector.hpp>
using namespace boost::assign;

int main(int argc, const char* argv[])
{
    using lloyd::json::value;
    using lloyd::json::element;
    using lloyd::json::null;
    lloyd::json::object obj;
    lloyd::json::object sobj;
    std::vector<value> t5;
    t5 += null(), true, false, value("Testing"), sobj;

    obj += element("T1", null()), element("T2", true), element("T3", false);
    obj += element("T4", "Testing 4"), element("T5", t5), element("T6", sobj);
    obj += element("NT0", (long)50), element("NT1", 50.5), element("NT2", 50.0);

    std::stringstream s;
    typedef boost::spirit::karma::ostream_iterator<char> out_itr;
    out_itr so(s);

    lloyd::json::karma::json_object_out_generator<out_itr> json_object_out;                 //  Our grammar definition
    boost::spirit::karma::generate(so, json_object_out(true, 0, 1), obj);
    std::cout << "Result:\n";
    std::cout << s.str() << std::endl;
    return 0;
}

表示される実際の問題をカバーするようにタイトルを変更するように編集しました。コード サンプルのアップロード ミスを修正するために編集しました。

4

1 に答える 1

1

誰かのコメントが述べているように、欠落しているのは、参照 (ここに存在する) を削除するのを逃したヘッダーですが、使用法を削除しました。

ただし、上記の実際の問題は、C++ の基本的なオブジェクト変換規則にあります。soemone がこれに遭遇した場合:

c は、ポインター型からブール値への直接変換を提供します。c++ は std::string クラスを追加します。そのクラスは、const char* からコンストラクターを提供します。

直接変換はクラス コンストラクターよりも単純であるため、いずれかを使用できる場合はその変換が優先されます。より単純なため、どの変換を使用するかについてあいまいであるとは見なされません。したがって、文字列への char* が意図されたものですが、コンパイラはブール値へのポインターを実行したため、出力がブール値になりました。

この情報は、freenode ##spirit チャット チャネルで VeXocide によって提供されました。

そのため、目的の変換を強制するために、"STRING HERE" の代わりに std::string("STRING HERE") を使用すると、うまくいきました。boost::spirit::karma は、ギゴの問題であったため、実際の問題とは関係がありませんでした。

于 2013-08-15T23:15:07.357 に答える