3

私は精神を高めるのが初めてで、次の問題があります。

#include <string>
#include <vector>
#include <boost/spirit/include/qi.hpp>

#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>

#include <boost/bind.hpp>

using namespace boost::spirit;
using namespace std;

struct MyGrammar
    : qi::grammar<string::const_iterator, string(), ascii::space_type> {
    MyGrammar();

    void myFun(const string& s);

    private:
    qi::rule<string::const_iterator, string(), ascii::space_type> myRule;
};



using namespace boost::spirit;
using namespace std;

MyGrammar::MyGrammar() : MyGrammar::base_type(myRule) {
    using qi::_1;

    myRule = int_ [boost::bind(&MyGrammar::myFun, this, _1)]; // fails
    myRule = int_ [_val = _1];  // fine
}

void MyGrammar::myFun(const string& s){
    cout << "read: " << s << endl;
}

int
main(){
}

最初の代入でmyRuleはコンパイル エラーが発生しますが、2 番目の代入では問題なくコンパイルされます。

最初のケースでは、コンパイラは私が理解できない巨大なエラー メッセージを出力します。最後に次のように述べています。

boost_1_49_0/include/boost/bind/bind.hpp:318:9: error: no match for call to '(const boost::_mfi::mf1<void, MyGrammar, const std::basic_string<char>&>) (MyGrammar* const&, const boost::phoenix::actor<boost::spirit::argument<0> >&)'
boost_1_49_0/include/boost/bind/mem_fn_template.hpp:163:7: note: candidates are: R boost::_mfi::mf1<R, T, A1>::operator()(T*, A1) const [with R = void, T = MyGrammar, A1 = const std::basic_string<char>&]
boost_1_49_0/include/boost/bind/mem_fn_template.hpp:184:7: note:                 R boost::_mfi::mf1<R, T, A1>::operator()(T&, A1) const [with R = void, T = MyGrammar, A1 = const std::basic_string<char>&]

何か案は?助けてくれてありがとう!

4

2 に答える 2

5

異なるbind実装のプレースホルダーを使用することはできません。現在bind、Boost には 3 つの関数があります。

  • boost::bind、に取って代わられる
  • boost::lambda::bind、に取って代わられる
  • boost::phoenix::bind、これは Boost.Spirit に使用する必要があります

boost::spirit::qi( と)の下のプレースホルダーboost::spirit::karmaは で使用されているものと同じなboost::phoenix::bindので、それを使用してください。

ああ、プロのヒント:using namespace std;グローバル名前空間のディレクティブを使用して、できれば他のものを停止します。

于 2012-05-25T16:47:45.103 に答える
3

最初の問題は、合成された属性として指定しますが、合成された属性が。であるstd::stringという観点からルールを定義することです。qi::int_int

2番目の問題は、Spiritのドキュメントで直接述べられているように、Phoenix以外のファンクターが1つではなく3つの引数を取ることです。

Boost.Bindを使用してメンバー関数をバインドできます。関数オブジェクトの場合、許可されるシグニチャは次のとおりです。

void operator()(Attrib const&, unused_type, unused_type) const;
void operator()(Attrib const&, Context&, unused_type) const;
void operator()(Attrib const&, Context&, bool&) const;

3番目の問題は、のプレースホルダー(実質的にグローバル名前空間にある)_1ではなく、SpiritのPhoenixプレースホルダーを使用していることです。boost::bind

要約すると、これは機能するはずです。

#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct MyGrammar :
    qi::grammar<std::string::const_iterator, int(), ascii::space_type>
{
    MyGrammar();
    void myFun(int i, qi::unused_type, qi::unused_type);

private:
    qi::rule<std::string::const_iterator, int(), ascii::space_type> myRule;
};

MyGrammar::MyGrammar() : MyGrammar::base_type(myRule)
{
    myRule = qi::int_[boost::bind(&MyGrammar::myFun, this, _1, _2, _3)];
}

void MyGrammar::myFun(int const i, qi::unused_type, qi::unused_type)
{
    std::cout << "read: " << i << '\n';
}

int main()
{
    std::string const input = "42";
    std::string::const_iterator first = input.begin(), last = input.end();
    qi::phrase_parse(first, last, MyGrammar(), ascii::space);
}

そうは言っても、boost::bindここで使用する特別な理由がない限り、boost::phoenix::bind代わりに次のものを使用する必要があります。

#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

struct MyGrammar :
    qi::grammar<std::string::const_iterator, int(), ascii::space_type>
{
    MyGrammar();
    void myFun(int i);

private:
    qi::rule<std::string::const_iterator, int(), ascii::space_type> myRule;
};

MyGrammar::MyGrammar() : MyGrammar::base_type(myRule)
{
    myRule = qi::int_[boost::phoenix::bind(&MyGrammar::myFun, this, qi::_1)];
}

void MyGrammar::myFun(int const i)
{
    std::cout << "read: " << i << '\n';
}

int main()
{
    std::string const input = "42";
    std::string::const_iterator first = input.begin(), last = input.end();
    qi::phrase_parse(first, last, MyGrammar(), ascii::space);
}

これにより、バインドされたメンバー関数は、最初に必要だったように、単一の引数(合成された属性)のみを取ることができます。

于 2012-05-25T16:59:53.283 に答える