1

Boost.Fusion ASSOC_STRUCT を返すルールがあります。ルールのパーサーによって解析された結果を _val に割り当てようとしていますが、うまくいきません。話をスキップして、関連するコードを直接紹介します。

#include <boost/fusion/include/define_assoc_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/spirit/include/qi_symbols.hpp>
#include <iostream>
#include <string>

namespace keys {
   struct actor_key;
   struct action_key;
   struct money_key;
 }

 BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    (), ActionLine,
    (int, action, keys::action_key)
    (int, amount, keys::money_key)
    (int, actor, keys::actor_key)
  )

int main ()
{
  namespace qi = boost::spirit::qi;
  using qi::_1;
  using qi::_2;
  using qi::_a;
  using qi::int_;
  using qi::lit;
  using boost::spirit::_val;
  using boost::fusion::as_vector;

  qi::symbols<char, int> name_parser_;
  name_parser_.add("name4", 4);

  std::string input("string1 ($7) string2 name4");
  std::string::const_iterator f(input.begin()), l(input.end());  
  ActionLine expected{0, 7, 4}, result;

  //The following rule is supposed to parse input of the form
  //"string1 ($[integer]) string2 [name]"
  //and return a triple (ActionLine) with the values { 0, value of (int_), value of (name_parser_) }
  qi::rule<std::string::const_iterator, ActionLine()> action_line_ =
     lit("string1 ($") >> int_ >> lit(") string2 ") >> name_parser_
     // [ _val = ActionLine{0, _1, _2} ]; // this is what I am trying to achieve
    [ _val = ActionLine{0, 7, 4} ]; //this compiles, but of course is not what I need

   bool b =
     qi::parse(f, l, action_line_, result) &&
     as_vector(result) == as_vector(expected);

   std::cout << "test: " << std::boolalpha << b << std::endl;
   return 0;
 }

(g++ above_file.cpp -std=c++0x でコンパイル) コンパイラ エラーは、この例と実際のアプリケーションでは多少異なりますが、( _val = ActionLine{0, _1, _2} の行で) : ::ActionLine::ActionLine() の呼び出しに一致する関数がなく、_1 と _2 を int に変換できないと思います。

また、ローカル int 変数を追加して、それらを使用して解析された値をコピーしようとしましたが、boost::phoenix::at(_1,0)、boost::phoenix::at(_1,1 ) (私はここでそれらのアイデアがスピリットのセマンティックアクションパラメータを高めることを発見しました)

4

1 に答える 1

2

必要なことphoenix::constructを行うには、セマンティックアクションで使用する必要があります。

#include <boost/fusion/include/define_assoc_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp> //CHANGE:you need to include this to use "phoenix::construct"
#include <boost/fusion/include/as_vector.hpp>
#include <boost/spirit/include/qi_symbols.hpp>
#include <iostream>
#include <string>

namespace keys {
   struct actor_key;
   struct action_key;
   struct money_key;
 }

 BOOST_FUSION_DEFINE_ASSOC_STRUCT(
    (), ActionLine,
    (int, action, keys::action_key)
    (int, amount, keys::money_key)
    (int, actor, keys::actor_key)
  )

int main ()
{
  namespace qi = boost::spirit::qi;
  namespace phx = boost::phoenix;
  using qi::_1;
  using qi::_2;
  using qi::_a;
  using qi::int_;
  using qi::lit;
  using boost::spirit::_val;
  using boost::fusion::as_vector;

  qi::symbols<char, int> name_parser_;
  name_parser_.add("name4", 4);

  std::string input("string1 ($7) string2 name4");
  std::string::const_iterator f(input.begin()), l(input.end());  
  ActionLine expected{0, 7, 4}, result;

  //The following rule is supposed to parse input of the form
  //"string1 ($[integer]) string2 [name]"
  //and return a triple (ActionLine) with the values { 0, value of (int_), value of (name_parser_) }
  qi::rule<std::string::const_iterator, ActionLine()> action_line_ =
     (lit("string1 ($") >> int_ >> lit(") string2 ") >> name_parser_) //CHANGE:the parentheses are important otherwise the semantic action would be attached to name_parser_
    [ _val = phx::construct<ActionLine>(0, _1, _2) ]; //CHANGE: you need to use phoenix to use the placeholders _1, _2, etc

   bool b =
     qi::parse(f, l, action_line_, result) &&
     as_vector(result) == as_vector(expected);

   std::cout << "test: " << std::boolalpha << b << std::endl;
   std::cout << at_key<keys::action_key>(result)<< ", " << at_key<keys::money_key>(result)<< ", " << at_key<keys::actor_key>(result) << std::endl;

   return 0;
 }
于 2013-01-18T11:03:05.540 に答える