C++ spirit解析器对上下文参数的操作中boost::bind(成员函数)出现编译错误

C++ spirit解析器对上下文参数的操作中boost::bind(成员函数)出现编译错误,c++,boost-spirit-qi,boost-bind,C++,Boost Spirit Qi,Boost Bind,我使用vc14,boost版本是1.60 #include <boost/config/warning_disable.hpp> #include <boost\spirit\home\qi.hpp> #include <boost\variant.hpp> #include <boost\spirit\include\qi.hpp> #include <boost\spirit\include\phoenix_core.hpp> #i

我使用vc14,boost版本是1.60

#include <boost/config/warning_disable.hpp>
#include <boost\spirit\home\qi.hpp>
#include <boost\variant.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>
#include <boost/phoenix/function/adapt_function.hpp>
#include <boost\spirit\include\phoenix_fusion.hpp>
#include <boost\foreach.hpp>
#include <string>
#include <list>
#include <boost\bind.hpp>
#define BOOST_SPIRIT_USE_PHOENIX_V3


namespace testParser {
        namespace qi = boost::spirit::qi;
        namespace ascii = boost::spirit::ascii;
        namespace sp = boost::spirit;
        namespace fu = boost::fusion;
        typedef sp::context<
            fu::cons<std::list<std::string>,fu::nil >,
            fu::vector0<> 
        >  context;

        class str_menager
        {
            qi::symbols<char> const& vistrings;

        public:
            typedef void result_type;
                        typedef void type;
            str_menager(qi::symbols<char> const& ss) :vistrings(ss) {  }
            void operator ()(std::string const& s, context& con, bool& m_Flag)
            {
                if (vistrings.find(s) != nullptr)
                {
                    using boost::phoenix::at_c;
                    (fu::at_c<0>(con.attributes)).push_back(s);
                }
                else
                {
                    m_Flag = false;
                }
            }
            void decide(std::string const& s, 
//              boost::spirit::qi::unused_type ,
                context& con,
                bool& m_Flag)

            {
                if (vistrings.find(s) != nullptr)
                {
                    using boost::phoenix::at_c;
                    (fu::at_c<0>(con.attributes)).push_back(s);
                }
                else
                {
                    m_Flag = false;
                }
            }
        };



        typedef std::list<std::string> strings;
        template <typename iterator, typename Skiper = ascii::space_type>
        struct stringParser :qi::grammar <iterator, strings(), Skiper>
        {
            stringParser() : stringParser::base_type(stringslist) {
                using boost::phoenix::at_c;
                using boost::spirit::qi::_val;
                using boost::spirit::qi::int_;



                using boost::spirit::qi::omit;
                using boost::spirit::qi::lexeme;
                using boost::spirit::ascii::alpha;
                using boost::spirit::qi::raw;
                using boost::spirit::qi::fail;
                using boost::spirit::_pass;
                using boost::spirit::false_;
                using boost::spirit::qi::on_error;
                using boost::phoenix::val;
                using boost::phoenix::construct;
                using boost::phoenix::ref;
                using boost::spirit::hold;


                str_menager controler(vistrings);
                name = raw[lexeme[*alpha]];
                stringslist =
                    *(
                        omit[("VIS" > name)[ref(vistrings) += qi::_1]
                        ] |
                        //hold[
                            name
                        //] > vistrings
                       [boost::bind(&str_menager::decide, &controler, _1, _2, _3)]
                        )
                    ;
                name.name("some_name");
                stringslist.name("stringslist");
                on_error<fail>
                    (stringslist,
                        std::cout << val("Error! Expectiong ")
                        << qi::_4
                        << val(" here: \"")
                        << construct<std::string>(qi::_3, qi::_2)
                        << val("\"")
                        << std::endl);
            }
            qi::symbols<char> vistrings;
            qi::rule<iterator, strings(), ascii::space_type> stringslist;
            qi::rule<iterator, std::string(), ascii::space_type> name;



        };
    }

void TestSS()
{
    std::string str = " VIS someString someString otherString";
    typedef std::string::const_iterator iterator_type;
    typedef testParser::stringParser<iterator_type> stringParser;

    stringParser strParser;

    iterator_type end = str.end();
    iterator_type iter = str.begin();

    testParser::strings strings;
    int i = 0;
    boost::spirit::ascii::space_type sp;
    bool r = boost::spirit::qi::phrase_parse(iter, end, strParser, sp, strings);

    BOOST_FOREACH(std::string const& p, strings)
    {
        std::cout << p << "\n";
    }

    std::cout << "\n";

}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义增强\u精神\u使用\u凤凰\u V3
命名空间测试分析器{
名称空间qi=boost::spirit::qi;
名称空间ascii=boost::spirit::ascii;
名称空间sp=boost::spirit;
名称空间fu=boost::fusion;
typedef sp::context<
傅:反对者,
fu::矢量0
>语境;
类stru动物园
{
qi::符号常量和vistrings;
公众:
typedef void result_type;
typedef-void型;
stru动物园(qi::symbols const&ss):vistrings(ss){}
void运算符()(std::string const&s、context&con、bool&m_标志)
{
if(vistrings.find(s)!=nullptr)
{
使用boost::phoenix::at_c;
(fu::at_c(con.attributes))。向后推;
}
其他的
{
m_标志=假;
}
}
void decision(标准::字符串常量&s,
//助推::精神::气::未使用的_类型,
上下文与上下文,
布尔和马尔旗)
{
if(vistrings.find(s)!=nullptr)
{
使用boost::phoenix::at_c;
(fu::at_c(con.attributes))。向后推;
}
其他的
{
m_标志=假;
}
}
};
typedef std::列表字符串;
模板
struct-stringParser:qi::grammar
{
stringParser():stringParser::基本类型(stringslist){
使用boost::phoenix::at_c;
使用boost::spirit::qi::_val;
使用boost::spirit::qi::int;
使用boost::spirit::qi::省略;
使用boost::spirit::qi::lexeme;
使用boost::spirit::ascii::alpha;
使用boost::spirit::qi::raw;
使用boost::spirit::qi::fail;
使用boost::spirit::u pass;
使用boost::spirit::false;
使用boost::spirit::qi::on_错误;
使用boost::phoenix::val;
使用boost::phoenix::construct;
使用boost::phoenix::ref;
使用boost::spirit::hold;
STRU动物园控制器(内脏);
name=raw[lexeme[*alpha]];
细条=
*(
省略[(“VIS”>名称)[ref(vistrings)+=qi::_1]
] |
//持有[
名称
//]>内管柱
[boost::bind(&str_-menager::decise,&controller,_1,_2,_3)]
)
;
名字。名字(“某个名字”);
stringslist.名称(“stringslist”);
论错误
(stringslist,

std::cout查看您的
成员函数的主体,您需要四件事:

  • a
    qi::symbols vistring
    ,它属于
    str_menager
    (因此不需要是参数)
  • 一个
    std::string s
    ,它是
    name
    的属性
  • 一个
    std::list
    ,它是
    stringslist
    的属性
  • 一个
    bool m_标志
    ,允许您在解析时发出失败信号
因此理想情况下,您的
decise
成员函数应该是:

void define(const std::string& s, std::list<std::string>& list, bool& m_Flag)
{
    if (vistrings.find(s) != nullptr)
    {
        list.push_back(s);
    }
    else
    {
        m_Flag = false;
    }
}
问题在于,由于
decise
是一个成员函数,因此Phoenix函数自适应宏不能直接工作(而且定义自己的
Phoenix::function
是一大堆样板文件)

:

请注意,您需要通过4(而不是3),以便考虑到还需要通过
str_menager
的实例(在这个主题上,您需要使
controller
成为语法的一个成员,因为在您的示例中,它的生命周期在构造函数完成时结束,但您尝试使用它很长时间)

下面是完整的示例:()


仅供参考,自从C++11使用std::bind(&str_-menager::decise,&controler,std::placeholders:::_1,std::placeholders::_2,std::placeholders::_3)以来,没有理由使用
boost::bind
我得到了:“错误C2338:元组索引超出范围”,但仍然没有work@typetraitor我本来打算抗议的,但显然你是对的。但是,在C++14之前,你不能使用lambda。非常感谢你的phoenix课程,它对我很有帮助:-)
name[adapted_decide(qi::_1,qi::_val,qi::_pass)]
BOOST_PHOENIX_ADAPT_FUNCTION(void,decide_,boost::mem_fn(&str_menager::decide),4);
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/foreach.hpp>
#include <string>
#include <list>
#include <boost/mem_fn.hpp>


namespace testParser {
        namespace qi = boost::spirit::qi;
        namespace ascii = boost::spirit::ascii;
        namespace sp = boost::spirit;
        namespace fu = boost::fusion;
        namespace phx = boost::phoenix;


        class str_menager
        {
            qi::symbols<char> const& vistrings;

        public:
            typedef void result_type;
                        typedef void type;
            str_menager(qi::symbols<char> const& ss) :vistrings(ss) {  }


            void decide(std::string const& s, 
                std::list<std::string>& list,
                bool& m_Flag)

            {
                if (vistrings.find(s) != nullptr)
                {
                    list.push_back(s);
                }
                else
                {
                    m_Flag = false;
                }
            }
        };

        BOOST_PHOENIX_ADAPT_FUNCTION(void,decide_,boost::mem_fn(&str_menager::decide),4);//you need to put here number_of_args+1 to take into account the instance parameter



        typedef std::list<std::string> strings;
        template <typename iterator, typename Skiper = ascii::space_type>
        struct stringParser :qi::grammar <iterator, strings(), Skiper>
        {
            stringParser() : stringParser::base_type(stringslist),vistrings(),controler(vistrings) {
                using boost::spirit::qi::omit;
                using boost::spirit::qi::lexeme;
                using boost::spirit::ascii::alpha;
                using boost::spirit::qi::raw;
                using boost::spirit::qi::fail;
                using boost::spirit::qi::on_error;
                using phx::val;
                using phx::ref;
                using phx::construct;


                name = raw[lexeme[*alpha]];
                stringslist =
                    *(
                        omit[("VIS" > name)[ref(vistrings) += qi::_1]
                        ] |
                            name
                       [decide_(&controler, qi::_1, qi::_val, qi::_pass)]
                        )
                    ;
                name.name("some_name");
                stringslist.name("stringslist");
                on_error<fail>
                    (stringslist,
                        std::cout << val("Error! Expectiong ")
                        << qi::_4
                        << val(" here: \"")
                        << construct<std::string>(qi::_3, qi::_2)
                        << val("\"")
                        << std::endl);
            }
            qi::symbols<char> vistrings;
            str_menager controler;
            qi::rule<iterator, strings(), ascii::space_type> stringslist;
            qi::rule<iterator, std::string(), ascii::space_type> name;



        };
    }

void parse(const std::string& str)
{
    typedef std::string::const_iterator iterator_type;
    typedef testParser::stringParser<iterator_type> stringParser;

    stringParser strParser;

    iterator_type end = str.end();
    iterator_type iter = str.begin();

    testParser::strings strings;
    boost::spirit::ascii::space_type sp;
    bool r = boost::spirit::qi::phrase_parse(iter, end, strParser, sp, strings);
    if(r)
    {
        std::cout << "Success.\n";
        BOOST_FOREACH(std::string const& p, strings)
        {
            std::cout << p << "\n";
        }
    }
    else
    {
        std::cout << "Something failed.\n";
    }
    if(iter!=end)
    {
        std::cout << "Unparsed: [" << std::string(iter,end) << "]";
    }

    std::cout << std::endl;
}

int main()
{
    parse(" VIS someString someString otherString");
    parse("VIS foo VIS bar foo bar baz");
    parse("VIS foo bar foo VIS bar baz");
}
void decide(const qi::symbols<char>& vistring, const std::string& s, std::list<std::string>& list, bool& m_Flag)
{
    //same as before
}
BOOST_PHOENIX_ADAPT_FUNCTION(void,decide_,decide,4);
...
name[decide_(phx::ref(vistring),qi::_1,qi::_val,qi::_pass)]
...