【问题标题】:boost::bind does not compileboost::bind 无法编译
【发布时间】:2012-05-25 16:25:25
【问题描述】:

我是提振精神的新手,遇到以下问题:

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

有什么想法吗? 非常感谢您的帮助!

【问题讨论】:

    标签: c++ boost boost-spirit boost-bind


    【解决方案1】:

    您不能使用来自不同 bind 实现的占位符。目前Boost中有三个bind函数:

    • boost::bind,被
    • 取代
    • boost::lambda::bind,被
    • 取代
    • boost::phoenix::bind,这是你应该用于 Boost.Spirit 的

    boost::spirit::qi(和boost::spirit::karma)下的占位符与boost::phoenix::bind使用的占位符相同,所以就用那个。

    哦,还有专业提示:停止您的 using namespace std;,最好停止全局命名空间中的任何其他 using 指令。

    【讨论】:

    • +1 - 我不太确定qi::_1 是否总是别名phoenix::qi,真的。我宁愿建议使用qi::_1(或者实际上是本地using namespace qi)。毕竟你用的是 Qi 库,没有必要使用内幕消息。
    【解决方案2】:

    第一个问题是您将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;
    

    第三个问题是您使用的是 Spirit 的 Phoenix _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);
    }
    

    这允许您的绑定成员函数只接受一个参数 - 综合属性 - 正如您最初想要的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多