![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Warming upBoost , Spirit 2.5.2 , Tutorials
|
![]() | Note |
---|---|
Когда мы объединяем генераторы, мы получаем «большой» генератор, но это все еще генератор. Генераторы могут становиться все больше и больше, гнездясь все больше и больше, но всякий раз, когда вы склеиваете два генератора вместе, вы в конечном итоге получаете один больший генератор. Это важная концепция. |
Теперь создание вывода для двух чисел не слишком интересно. Давайте создадим генератор, который будет выводить нуль или больше чисел с плавающей запятой подряд.
*double_
Это как обычная звезда Клин. Мы перенесли<*
>на фронт по тем же причинам, что и в.Дух.Qi: Мы должны работать с синтаксическими правилами C++. Но если вы знаете регулярные выражения (и наверняка помните эти правила синтаксиса C++), это будет выглядеть очень знакомым в течение очень короткого времени.
Любое выражение, которое оценивается генератором, может быть использовано со звездой Клин. Однако имейте в виду, что из-за правил приоритета оператора C++ вам может потребоваться поместить выражение в скобки для сложных выражений. Как и выше, белое пространство может быть вставлено неявно между генерируемыми числами, если это необходимо.
Мы следуем примеру раздела разогреваSpirit.Qiи создадим генератор, который производит список чисел, ограниченный запятой.
double_ << *(lit(',') << double_)
Уведомление<lit(',')
>. Это буквальный генератор символов, который просто генерирует запятую<','
>. В этом случае звезда Клин изменяет более сложный генератор, а именно тот, который генерируется выражением:
(lit(',') << double_)
Обратите внимание, что это тот случай, когда скобки необходимы. Звезда Клин включает в себя полное выражение выше, повторяя весь шаблон в генерируемом выходе ноль или более раз.
Мы закончили с определением генератора. Осталось только вызвать генератор, чтобы он выполнил свою работу. Сейчас мы используем функцию<generate_delimited
>. Одна перегрузка этой функции принимает четыре аргумента:
Сравнивая этот минимальный пример с эквивалентным парсерным примером, мы замечаем значительную разницу. Возможно (и, на самом деле, имеет большой смысл) использовать парсер без создания какого-либо внутреннего представления парсированного ввода (т.е. без «производства» каких-либо данных из парсированного ввода). Использование парсера в этом режиме проверяет предоставленный вход на заданное выражение парсера, позволяющее проверить, является ли вход парсерным. Для генераторов этот режим не имеет никакого смысла. Что такое генерация продукции без создания какой-либо продукции? Поэтому нам всегда придется предоставлять данные, из которых должен быть получен выход. В нашем примере мы приводим список чисел<double
>в качестве последнего параметра функции<generate_delimited
>(см. код ниже).
В этом примере мы хотим разграничить генерируемые числа пространствами. Другой генератор, названный<space
>, входит в репертуар Духа предопределенных генераторов. Это очень тривиальный генератор, который просто создает пространства. Это эквивалентно написанию<lit(' ')
>или просто<' '
>. Она реализована для сходства с соответствующим предопределенным<space
>парсером. Мы будем использовать<space
>в качестве разграничителя. Делимитер - это тот, который отвечает за вставку символов между элементами генератора, такими как<double_
>и<lit
>.
Хорошо, теперь давайте создадим (для полного исходного кода этого примера, пожалуйста, обратитесь кnum_list1.cpp).
template <typename OutputIterator> bool generate_numbers(OutputIterator& sink, std::list<double> const& v) { using karma::double_; using karma::generate_delimited; using ascii::space; bool r = generate_delimited( sink, // destination: output iterator double_ << *(',' << double_), // the generator space, // the delimiter-generator v // the data to output ); return r; }
![]() | Note |
---|---|
Вы можете задаться вопросом, как< |
Функция генерации возвращает<true
>или<false
>в зависимости от результата выходной генерации. Как указано в различных местах этой документации, генератор может выйти из строя по разным причинам. Одной из возможных причин является ошибка в базовом выходном итераторе (исчерпанная память или полный диск и т.д.). Другая причина может заключаться в том, что данные не соответствуют требованиям конкретного генератора.
![]() | Note |
---|---|
< Внимательный читатель может заметить, что выражение генератора имеет< Проблема с пропуском< |
Обратите внимание, что мы включили генератор непосредственно в вызов<generate_delimited
>. Называя эту функцию, выражение оценивает в временный, неназванный генератор, который передается в функцию<generate_delimited
>, используется, а затем разрушается.
Здесь мы решили сделать функцию генерации общей, сделав ее шаблоном, параметризованным типом итератора вывода. При этом он может помещать сгенерированные данные в любой итератор вывода, соответствующий STL.
Статья Warming up раздела Spirit 2.5.2 Tutorials может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
реклама |