2013-04-04 3 views
3

Я пытаюсь сопоставить некоторые обработчики ключевых слов (методы) с помощью qi :: символов со значениями типа boost :: function. Итак, если найдено ключевое слово, я хочу вызвать метод. Но я не мог привязать метод с этой карты. Компилятор завершился с ошибкой в ​​phoenix :: bind. Что я делаю неправильно?Как связать/вызвать boost :: функцию, хранящуюся в fusion :: vector from spirit semantic rule?

Часть кода ниже:

template <typename Iterator> 
struct Grammar : qi::grammar<Iterator, AST::FunctionCall(), ascii::space_type> 
{ 
    Grammar(): 
     Grammar::base_type(query), 
    { 
     ... 
     operand = 
      predicate [phoenix::bind(phoenix::at_c<0>(qi::_1), this, phoenix::at_c<1>(qi::_1))]; // **Compiler fails here** 
     ... 

     predicate = 
      (pred_tbl > '(') 
     > -(primary_expr % ',') 
     > ')'; 
     ... 

     pred_tbl.add 
      ("composing", &RQL::composing) 
     ); 
    } 

    qi::rule<Iterator, fusion::vector<Predicate, PredicateArgList>(), ascii::space_type> predicate; 

    typedef std::vector<AST::Value> PredicateArgList; 
    typedef boost::function<void (Grammar*, const PredicateArgList& args)> Predicate; 
    qi::symbols<char, Predicate> pred_tbl; 

    void composing(const PredicateArgList& args); 
}; 

ошибки компилятора:

error C2903: 'result' : symbol is neither a class template nor a function template c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 115 
error C2039: 'result' : is not a member of 'boost::function<Signature>' c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 115 
error C2059: syntax error : '<' c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 115 
error C2238: unexpected token(s) preceding ';' c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 116 
error C2065: 'function_apply' : undeclared identifier c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 124 
error C2955: 'boost::mpl::eval_if' : use of class template requires template argument list c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 125 
error C2146: syntax error : missing ';' before identifier 'type' c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 126 
error C3254: 'boost::phoenix::detail::function_eval<2>::result<Env,F,A0,A1>' : class contains explicit override 'type' but does not derive from an interface that contains the function declaration c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 126 
error C2838: 'type' : illegal qualified name in member declaration c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 126 
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 126 
error C2602: 'boost::phoenix::detail::function_eval<2>::result<Env,F,A0,A1>::type' is not a member of a base class of 'boost::phoenix::detail::function_eval<2>::result<Env,F,A0,A1>' c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 126 
error C2868: 'boost::phoenix::detail::function_eval<2>::result<Env,F,A0,A1>::type' : illegal syntax for using-declaration; expected qualified-name c:\work\include\boost-1_41\boost\spirit\home\phoenix\core\detail\function_eval.hpp 126 
+0

Я нашел обходной путь для этой проблемы:

1. Заменить сложный предикат [феникс :: связывают с:
'операндов = [феникс: : связать (& RQL :: dispatchPredicate, это ци :: _ 1)] ... пустота dispatchPredicate (Const фьюжн :: вектор & v) { \t фьюжн :: at_c <0> (v) (это, fusion :: at_c <1> (v)); } '

+2

Мне было довольно сложно создать что-то приятное из вашего - сломанного образца. Почему бы вам не сделать это [SSCCE] (http://meta.stackexchange.com/questions/22754/sscce-how-to-provide-examples-for-programming-questions/22762#22762) в следующий раз? Как показывает мой ответ, это было бы не намного больше - для вас. – sehe

ответ

2

Я полагаю, что недостающее звено могло быть

#define BOOST_SPIRIT_USE_PHOENIX_V3 

Посмотреть жить на http://liveworkspace.org/code/3uvyb4$1

Он печатает

Hello world from 'Grammar::composing(PredicateArgList const&)' args:3 

, как и ожидалось.

ОБНОВЛЕНИЕ PS. Я бы, наверное, предпочел писать привязки вызова следующим образом:

Grammar(): Grammar::base_type(predicate) 
{ 
    using phx::bind; 
    using namespace qi; 

    as<PredicateArgList> coerce; 

    predicate = 
     (pred_tbl > '(' 
        > coerce [ -(primary_expr % ',') ] 
        > ')') 
     [ phx::bind(_1, this, _2)] 
     ; 

    // ... 

Я думаю, что это гораздо яснее с _1 и _2 вместо из at_c<n> заклятий.

Вот код для справки:

#define BOOST_SPIRIT_USE_PHOENIX_V3 
#include <boost/function.hpp> 
#include <boost/phoenix/fusion.hpp> 
#include <boost/spirit/include/phoenix.hpp> 
#include <boost/spirit/include/qi.hpp> 

namespace qi  = boost::spirit::qi; 
namespace fusion = boost::fusion; 
namespace ascii = boost::spirit::ascii; 
namespace phx = boost::phoenix; 

namespace AST 
{ 
    struct FunctionCall {}; 
    using Value = int; 
} 

template <typename Iterator> 
struct Grammar : qi::grammar<Iterator, AST::FunctionCall(), ascii::space_type> 
{ 
    Grammar(): Grammar::base_type(predicate) 
    { 
     using phx::bind; 
     using namespace qi; 

     as<PredicateArgList> coerce; 

     predicate = 
      (pred_tbl > '(' 
         > coerce [ -(primary_expr % ',') ] 
         > ')') 
      [ phx::bind(_1, this, _2)] 
      ; 

     pred_tbl.add 
      ("composing", &Grammar::composing) 
     ; 

     primary_expr = qi::int_; 
    } 

    typedef std::vector<AST::Value> PredicateArgList; 
    typedef boost::function<void (Grammar*, PredicateArgList const&)> Predicate; 
    qi::symbols<char, Predicate> pred_tbl; 

    qi::rule<Iterator, AST::Value(), ascii::space_type> primary_expr; 
    qi::rule<Iterator, AST::FunctionCall(), ascii::space_type> predicate; 

    void composing(const PredicateArgList& args) 
    { 
     std::cout << "Hello world from 'Grammar::composing(PredicateArgList const&)' args:" << args.size() << "\n"; 
    } 
}; 

int main() 
{ 
    const std::string input("composing (1, 2, 3)"); 
    auto f = begin(input), l = end(input); 

    Grammar<decltype(f)> p; 

    bool ok = qi::phrase_parse(f,l,p,ascii::space); 
    return ok?0:255; 
} 
+0

Спасибо за вашу большую помощь! Жаль, но я вынужден использовать boost 1.41, и эта версия не поддерживает phoenix v3 (нет макроса BOOST_SPIRIT_USE_PHOENIX_V3). Я использовал w/a с диспетчерской функцией, как я описал в своем первом комментарии к исходному сообщению. –

+0

Mmm. Отсутствие Phoenix v3 является незначительной проблемой по сравнению с другими ошибками, исправленными с этой версии. Кто/что заставляет вас использовать эту версию? Вы понимаете, что Boost Spirit - это только заголовок, верно? Я бы сказал, посмотрите на [BCP] (http://stackoverflow.com/questions/13418918/using-boost-unordered-map/13423990#13423990) один раз. (PS. Мне пришлось исправить ошибку в 1_41_0 tst.hpp, чтобы получить 'qi :: symbols' для компиляции в первую очередь - eek!) – sehe

 Смежные вопросы

  • Нет связанных вопросов^_^