После исправления этой декларации правила:
typedef boost::function<char(char const*)> Func;
qi::rule<Iterator, Func()> start;
он работал: Live On Coliru (C++ 03).
UPDATE:
Почему я в конечном итоге с такой сложной штуковине?
qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1)
Хорошо. Позвольте мне рассказать вам о радости комплексообразования функционального состава с ленивым вычислениям (в C++ шаблон мета-программирования, который имеет эти сюрпризы со ссылкой/значение семантики): Не сделать следующее:
qi::_val = px::lambda(_a = qi::_1) [arg1[_a]] // UB!!! DON'T DO THIS
В зависимости от компилятор, уровень оптимизации, это может * появляется для работы. Но он вызывает неопределенное поведение [1]. Проблема заключается в том, что qi::_1
будет храниться как ссылка на атрибут, выставленный выражением парсера qi::int_
. Однако эта ссылка, после того как срок жизни контекста синтаксического анализа завершился, является обманутой ссылкой.
Итак, оценивая косвенные функции через недопустимую ссылку. Чтобы избежать этого, следует сказать (Live On Coliru):
qi::_val = px::lambda(_a = px::val(qi::_1)) [arg1[_a]]
или даже (если вам нравится неясного код):
qi::_val = px::lambda(_a = +qi::_1) [arg1[_a]]
Или, вы знаете, вы можете придерживаться связанной вложенным лямбда, поскольку привязка по умолчанию к значению-семантике для qi::_1
(если вы не использовали обертки phx::cref
/phx::ref
).
Я надеюсь, что вышеприведенный анализ гонит домой пункт, который я сделал в комментариях ранее:
Обратите внимание, что я бы не рекомендовал этот код стиля.Программирование более высокого порядка с Phoenix достаточно сложно, не составив их из ленивых актеров в некотором встроенном шаблоне выражения DSL: qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1)
. 'Nuff said?
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/function.hpp>
namespace qi = boost::spirit::qi;
namespace px = boost::phoenix;
typedef boost::function<char(char const*)> Func;
int main()
{
typedef std::string::const_iterator Iterator;
using namespace boost::phoenix::arg_names;
qi::rule<Iterator, Func()> start;
start = qi::int_
[ qi::_val = px::bind(px::lambda[arg1[arg2]], px::lambda[arg1], qi::_1) ];
// or: [ qi::_val = px::lambda(_a = px::val(qi::_1))[arg1[_a]] ];
static char const* inputs[] = { "0", "1", "2", "3", "4", 0 };
for (char const* const* it = inputs; *it; ++it)
{
std::string const input(*it);
Iterator f(input.begin()), l(input.end());
Func function;
bool ok = qi::parse(f, l, start, function);
if (ok)
std::cout << "Parse resulted in function() -> character "
<< function("Hello") << "; "
<< function("World") << "\n";
else
std::cout << "Parse failed\n";
if (f != l)
std::cout << "Remaining unparsed: '" << std::string(f, l) << "'\n";
}
}
Печать
Parse resulted in function() -> character H; W
Parse resulted in function() -> character e; o
Parse resulted in function() -> character l; r
Parse resulted in function() -> character l; l
Parse resulted in function() -> character o; d
[1] (MSVC2013 появился сбой, GCC может появиться работать в -O3, но в -O0 ошибку сегментации)
Спасибо, что ответили, но, к сожалению, я не думаю, что это разрешает мой вопрос. Если я что-то не хватает, приведенный выше код, похоже, игнорирует целое число, которое было проанализировано, и это то, что я пытался включить. Я хочу, чтобы вход был «2», а 'output (« Hello »)' должен быть 'e'. Вы знаете, как я могу это сделать? – user2913094
@ пользователь2913094 Wokay. Я обновил образец, чтобы быть более полным. Обратите внимание, что я бы не рекомендовал этот стиль кода. Программирование более высокого порядка с Phoenix достаточно сложно, не составив их из ленивых участников в каком-то встроенном шаблоне выражения DSL: 'qi :: _ val = px :: bind (px :: lambda [arg1 [arg2]], px :: lambda [arg1], qi :: _ 1) '. *** Нафф сказал ***? – sehe
Похоже, хороший совет. Альтернативы (например, создание класса функтора и вообще избегание лямбда) немного неуклюжи, но, по крайней мере, они понятны. Благодаря! – user2913094