2012-05-25 106 views
3

我是新來提振精神,我有以下問題:的boost ::綁定不編譯

#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第一任務,我得到,而第二次分配編譯罰款編譯錯誤。

在第一種情況下,編譯器輸出我不明白的巨大錯誤消息。 最後它說:

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>&] 

任何想法? 非常感謝您的幫助!

回答

3

第一個問題是,您將std::string指定爲您的綜合屬性,但接下來根據qi::int_定義您的規則,其合成屬性爲int

的第二個問題是,作爲Spirit docs狀態直接,非鳳凰函子三個參數,而不是一個:

您可以使用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; 

第三個問題是,你使用精神的鳳凰_1佔位符,而不是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); 
} 

這使得您的綁定成員函數只需要一個參數–合成屬性–就像您最初想要的那樣。

5

您不能使用來自不同bind實現的佔位符。目前有三個bind功能提升:

  • boost::bind,通過
  • boost::lambda::bind取代,由
  • boost::phoenix::bind,這是你應該使用什麼Boost.Spirit

下的佔位符代替boost::spirit::qi(和boost::spirit::karma)與boost::phoenix::bind使用的相同,所以請使用它。

呵呵,專家提示:停止你的using namespace std;,最好在全局命名空間中使用其他指令。

+0

+1 - 我不太確定'qi :: _ 1'是否會永遠別名'phoenix :: qi',真的。我寧願建議使用'qi :: _ 1'(或者實際上,在本地'使用命名空間qi')。畢竟,您正在使用Qi庫,並且不需要使用內部信息。 – sehe