Благодаря ссылкам, на которые мне указали @sehe и @drus, и обнаружив около qi::omit
, я понимаю, что могу связать семантическое действие и затем опустить результат.
Формат, который я должен обработать, является избыточным (размер избыточен с количеством элементов), поэтому я должен семантически опустить что-то в любом случае.
using namespace sqi;
std::string const v_str = "3 AA BB CC";
{
std::vector<std::string> v;
auto it = begin(v_str);
bool r = sqi::phrase_parse(
it, end(v_str),
omit[int_] >> *lexeme[+(char_-' ')],
space, v
);
assert( v.size() == 3 and v[2] == "CC" );
}
Но это не значит, что я не могу использовать пропущенную (избыточную) часть для целей оптимизации или проверки согласованности.
{
std::vector<std::string> v;
auto it = begin(v_str);
bool r = sqi::phrase_parse(
it, end(v_str),
omit[int_[([&](int n){v.reserve(n);})]] >> *lexeme[+(char_-' ')],
space, v
);
assert( v.size() == 3 and v[2] == "CC" );
}
Я согласен с тем, что семантические действия являются злом, но, на мой взгляд, только когда они меняют состояние объектов-приемников.
Можно утверждать, что reserve
не меняет состояние вектора.
Фактически, таким образом я могу оптимизировать использование памяти с помощью reserve
, а также выполнение синтаксического анализатора, используя repeat
вместо неограниченного клина *
. (очевидно, repeat
может быть более эффективным) .
{
std::vector<std::string> v;
auto it = begin(v_str);
int n;
bool r = sqi::phrase_parse(
it, end(v_str),
omit[int_[([&](int nn){v.reserve(n = nn);})]] >> repeat(phx::ref(n))[lexeme[+(char_-' ')]],
space, v
);
assert( n == v.size() and v.size() == 3 and v[2] == "CC" );
}
(unsing phx::ref
является основополагающим, потому что оценка n
должна быть отложена)