80

質問は一番下に太字で示され、問題は最後に蒸留コードの断片によって要約されています。

型システム (型システムは型から文字列へと型から文字列へ) を単一のコンポーネント (Lakos で定義されている) に統合しようとしています。これを達成するために、、、boost::arrayおよびboost::variantを使用しています。boost::mpl型のパーサーとジェネレーターのルールをバリアントに統合したいと考えています。未定義の型、int4 (下記参照) 型、および int8 型があります。バリアントは次のように読み取りますvariant<undefined, int4,int8>

int4 の特徴:

    struct rbl_int4_parser_rule_definition
    {
      typedef boost::spirit::qi::rule<std::string::iterator, rbl_int4()> rule_type;
      
      boost::spirit::qi::int_parser<rbl_int4> parser_int32_t;
      
      rule_type rule;
      
      rbl_int4_parser_rule_definition()
      {
        rule.name("rbl int4 rule");
        rule = parser_int32_t;  
      }
    };
    
    template<>
    struct rbl_type_parser_rule<rbl_int4>
    {
      typedef rbl_int4_parser_rule_definition string_parser;
    };

上記のバリアントは未定義として開始し、その後ルールを初期化します。問題が発生し、50 ページのエラーが発生しましたが、最終的に追跡することができました.Variant はoperator=割り当て中に使用され、aboost::spirit::qi::int_parser<>は別のもの (operator=) に割り当てることができません。

対照的に、未定義の型に問題はありません。

    struct rbl_undefined_parser_rule_definition
    {
      typedef boost::spirit::qi::rule<std::string::iterator, void()> rule_type;
      rule_type rule;
      
      rbl_undefined_parser_rule_definition()
      {
        rule.name("undefined parse rule");
        rule = boost::spirit::qi::eps;
      }
    };
    
    template<>
    struct rbl_type_parser_rule<rbl_undefined>
    {
      typedef rbl_undefined_parser_rule_definition string_parser;
    };

問題の抽出:

    #include <string>
    #include <boost/spirit/include/qi.hpp>
    #include <boost/variant.hpp>
    #include <boost/cstdint.hpp>
    
    typedef boost::spirit::qi::rule<std::string::iterator,void()> r1;
    typedef boost::spirit::qi::rule<std::string::iterator,int()> r2;
    
    typedef boost::variant<r1,r2> v;
    
    int main()
    {
      /*
      problematic
      boost::spirit::qi::int_parser<int32_t> t2;
      boost::spirit::qi::int_parser<int32_t> t1;
      
      
      t1 = t2;
      */
    
      //unproblematic
      r1 r1_;
      r2 r2_;
      r1_ = r2_;
    
      v v_;
      // THIS is what I need to do.
      v_ = r2();
    }

具体的なパーサーとルールの間にはセマンティック ギャップがあります。私の脳は現在喫煙しているので、実用主義について考えるつもりはありません.私の質問は、どうすればこの問題を解決できるでしょうか? この問題を解決するための 3 つのアプローチを考えることができます。

one:静的関数メンバー:

    struct rbl_int4_parser_rule_definition
    {
      typedef boost::spirit::qi::rule<std::string::iterator, rbl_int4()> rule_type;
      
      //boost::spirit::qi::int_parser<rbl_int4> parser_int32_t;
      
      rule_type rule;
      
      rbl_int4_parser_rule_definition()
      {
        static boost::spirit::qi::int_parser<rbl_int4> parser_int32_t;
    
        rule.name("rbl int4 rule");
        rule = parser_int32_t;  
      }
    };

アプローチ1はスレッドセーフコードを防ぐと思いますか? ?

2:統合パーサーは shared_ptr にラップされます。私が型付けシステムの TMP に悩まされている理由は 2 つあります。ポインターを使用すると、最初の理由が無効になります。

3: operator= は no-op として定義されています。lhsバリアントは、割り当て前にデフォルトで構築されることを保証します。

編集: オプション3が最も理にかなっていると思います(operator =はノーオペレーションです)。ルール コンテナが作成されると変更されず、タイプのルール トレイトをそのオフセットに強制的に割り当てるだけです。

4

1 に答える 1

11

質問の全容を理解しているかどうかはわかりませんが、いくつかのヒントを以下に示します

  • でコメントされた行は// THIS is what I need to do.、私と一緒にうまくコンパイルされます(問題は解決しましたか?実際には、ルールではなくパーサーを割り当てることを意味していたと思いますか?)

  • function-local の初期化はstatic、最新の標準 (C++11) でスレッド セーフになるように定義されています。C++0x スレッドに対するコンパイラのサポートを確認してください。(ところで、初期化子がスローした場合、初期化ステートメントのパスは再度初期化を試みます)。

  • 規則alias()

    http://boost-spirit.com/home/articles/doc-addendum/faq/#aliasesで説明されているように

    proto 式を実際に値コピーすることなく、ルールの「論理コピー」を作成できます。FAQ にあるように、これは主に遅延バインディングを許可するためのものです。

  • Nabialek Trickはまさにあなたが必要としているものかもしれません。基本的には、後続の解析のためにパーサーを遅延選択します

    one = id;
    two = id >> ',' >> id;
    
    keyword.add
        ("one", &one)
        ("two", &two)
        ;
    
    start = *(keyword[_a = _1] >> lazy(*_a));
    

    あなたのコンテキストでは、次のようにkeyword定義されていることがわかります

    qi::symbols<char, qi::rule<Iterator>*> keyword;
    

    セマンティック アクションの属性を使用してすべての作業を行います。あるいは、

    qi::symbols<char, qi::rule<Iterator, std::variant<std::string,int>() >*> keyword;
    
  • ルールを同じタイプにします (基本的に、前の行で示したように)。

    これは私が混乱している部分です: あなたは型システムを統一したいと言っています。strongtyped パーサー (個別の属性シグネチャ) は必要ないかもしれません。

    typedef boost::variant<std::string,int> unified_type;
    typedef qi::rule<std::string::iterator, unified_type() > unified_rule;
    
    unified_rule rstring = +(qi::char_ - '.');
    unified_rule rint    = qi::int_;
    
    unified_rule combine = rstring | rint;
    
于 2012-02-02T09:34:35.160 に答える