Моя цель - создать временное решение, чтобы я мог использовать lambdas C++ 11 внутри смысловых действий Boost Spirit Qi, доступ к более расширенному набору заполнителей qi, таких как qi :: _ pass или qi :: _ r1, без необходимости вручную извлекать их из контекстного объекта. Я хочу избежать написания Phoenix lambdas для некоторой нетривиальной логики синтаксического анализа, предпочитая более прямой синтаксис C++ и семантику, доступную внутри C++ 11 lambdas.Phoenix :: bind для C++ 11 lambdas в boost :: spirit :: qi семантические действия
В приведенном ниже коде представлена идея, которую я использую для обходного пути. Идея состоит в том, чтобы использовать phoenix :: bind для привязки к лямбда и передать ей конкретные заполнители, которые мне нужны. Тем не менее, я получаю чрезвычайно длинную templated ошибку компилятора (gcc 4.7.0, Boost 1.54), что у меня нет опыта для интерпретации. Я выбрал то, что, по моему мнению, является наиболее важной частью и разместил его под кодом.
Я хотел бы знать, возможно ли, что я пытаюсь сделать в этом коде, с Boost Spirit, и если кто-нибудь может интерпретировать сообщение об ошибке для меня и сказать мне, что происходит не так.
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace phoenix = boost::phoenix;
int main() {
std::string input{"test1 test2 test3 FOO!"};
typedef decltype(input.begin()) StringIter;
qi::rule<StringIter, std::string()> parser =
*(
qi::char_
[
phoenix::bind(
[] (char value) {
std::cerr << value << std::endl;
},
qi::_1
)
]
);
qi::parse(input.begin(), input.end(), parser);
}
(Примечание: Я знаю, что конкретная задача, выполняемая этот код будет проще с прямыми конструкциями Феникса, или может даже быть сделана благодаря обновлениям Boost Духа, которые позволяют одноаргументный C++ 11 lambda напрямую, так как он использует только разобранное значение (qi :: _ 1). Тем не менее, это хороший минимальный пример того, что я хотел бы сделать, и если я могу заставить его работать, он должен легко обобщать .)
И, немного ошибки компилятора (через STLfilt):
test\testSpiritLearning.cpp:28:9: required from here
D:\programming\lib\boost\boost_1_54_0/boost/spirit/home/support/action_dispatch.hpp:178:13:
error: no match for call to '(
const boost::phoenix::actor<
boost::phoenix::composite<
boost::phoenix::detail::function_eval<1>
, boost::fusion::vector<
boost::phoenix::value<main()::<lambda(char &)> >
, boost::spirit::argument<0>, boost::fusion::void_
, boost::fusion::void_, boost::fusion::void_
, boost::fusion::void_, boost::fusion::void_
, boost::fusion::void_, boost::fusion::void_
, boost::fusion::void_
>
>
>
) (
boost::spirit::traits::pass_attribute<
boost::spirit::qi::char_class<
boost::spirit::tag::char_code<
boost::spirit::tag::char_
, boost::spirit::char_encoding::standard
>
>, char, void
>::type &
, boost::spirit::context<
boost::fusion::cons<basic_string<char> &, boost::fusion::nil>
, boost::fusion::vector0<>
> &, bool &
)'
Большое спасибо, что действительно исправляет ошибки компилятора. Из любопытства я также пробовал это с каждым дополнением, которое было прокомментировано по очереди; но он работал только с обоими комментариями. Теперь мне любопытно понять, с кем это работает. –
@anthrond Конечно, я упомянул _both_ по какой-то причине :) Я добавил небольшое объяснение. Cheers – sehe
Отлично, ваше объяснение объясняет это мне. –