![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Increment the Iterator pointing into a Container AttributeBoost , Spirit 2.5.2 , Extract Attribute Values to Generate Output from a Container (Karma)
|
![]() | Note |
---|---|
Этот файл заголовка не должен быть включен непосредственно какой-либо пользовательской программой, поскольку он обычно включается другими файлами заголовка Spirit, основанными на его содержании. |
Имя |
---|
< |
template <typename Iterator, typename Enable> struct next_iterator { static void call(Iterator& it); };
Параметр |
Описание |
по умолчанию |
---|---|---|
< | Тип< | Нет |
< | Параметр шаблона помощника, используемый для выборочного включения или отключения определенных специализаций< | < |
Notation
Iterator
Тип итератора.
it
Пример итератора типа<Iterator
>.
C
Тип контейнера, тип итератора которого<Iterator
>.
выражение |
Семантика |
---|---|
< | Увеличьте итератор так, чтобы он указывал на следующий элемент. |
Духпредопределяет специализацию этой точки настройки для нескольких типов. В следующей таблице перечислены эти типы вместе с типами, возвращаемыми встроенным typedef<type
>:
Параметры шаблонов |
Семантика |
---|---|
< | Исполнители< |
< | Ничего не делает. |
Точка настройки<next_iterator
>должна быть реализована для конкретного типа итератора, когда контейнер, к которому принадлежит этот итератор, должен использоваться в качестве атрибута вместо контейнера STL. Он применим для генераторовДуха. Только карма. Как правило, он должен быть реализован всякий раз, когда определенный тип итератора принадлежит контейнеру, который должен быть передан в качестве атрибута генератору, обычно подвергающему контейнер STL<C
>, и если тип контейнера не подвергает интерфейс контейнера STL (то есть<is_container<C>::type
>обычно возвращается<mpl::false_
>).
Если эта точка настройки реализована, могут потребоваться также следующие другие точки настройки.
Имя |
Когда внедрять |
---|---|
Необходимо внедрять всякий раз, когда тип должен использоваться в качестве атрибута контейнера в.Карма | |
Вот файлы заголовка, необходимые для компиляции примерного кода ниже:
#include <boost/spirit/include/karma.hpp> #include <iostream> #include <string> #include <vector>
Пример (полный исходный код см. здесь:customize_use_as_container.cpp) использует структуру данных
namespace client { struct use_as_container { // Expose a pair holding a pointer to the use_as_container and to the // current element as our iterator. // We intentionally leave out having it a 'operator==()' to demonstrate // the use of the 'compare_iterators' customization point. struct iterator { iterator(use_as_container const* container, int const* current) : container_(container), current_(current) {} use_as_container const* container_; int const* current_; }; // expose 'int' as the type of each generated element typedef int type; use_as_container(int value1, int value2, int value3) : value1_(value1), value2_(value2), value3_(value3) {} int value1_; std::string dummy1_; // insert some unrelated data int value2_; std::string dummy2_; // insert some more unrelated data int value3_; }; }
В качестве прямого атрибута кСписку<%
>генератору. Этот тип не раскрывает ни один из интерфейсов контейнера STL. Он даже не раскрывает привычную семантику контейнера. Целью этого искусственного примера является демонстрация того, как точки настройки могут использоваться для раскрытия независимых элементов данных в виде единого контейнера. Пример показывает, как включить его использование в качестве атрибута.Кармаповторяющиеся генераторы.
Чтобы сделать эту структуру данных совместимой, нам нужно специализироваться на нескольких точках настройки атрибутов:<traits::is_container
>,<traits::container_iterator
>,<traits::begin_container
>и<traits::end_container
>. Кроме того, мы специализируемся на всех точках настройки, связанных с итератором:<traits::deref_iterator
>,<traits::next_iterator
>и<traits::compare_iterators
>.
// All specializations of attribute customization points have to be placed into // the namespace boost::spirit::traits. // // Note that all templates below are specialized using the 'const' type. // This is necessary as all attributes in Karma are 'const'. namespace boost { namespace spirit { namespace traits { // The specialization of the template 'is_container<>' will tell the // library to treat the type 'client::use_as_container' as a // container holding the items to generate output from. template <> struct is_container<client::use_as_container const> : mpl::true_ {}; // The specialization of the template 'container_iterator<>' will be // invoked by the library to evaluate the iterator type to be used // for iterating the data elements in the container. We simply return // the type of the iterator exposed by the embedded 'std::vector<int>'. template <> struct container_iterator<client::use_as_container const> { typedef client::use_as_container::iterator type; }; // The specialization of the templates 'begin_container<>' and // 'end_container<>' below will be used by the library to get the iterators // pointing to the begin and the end of the data to generate output from. // // The passed argument refers to the attribute instance passed to the list // generator. template <> struct begin_container<client::use_as_container const> { static client::use_as_container::iterator call(client::use_as_container const& c) { return client::use_as_container::iterator(&c, &c.value1_); } }; template <> struct end_container<client::use_as_container const> { static client::use_as_container::iterator call(client::use_as_container const& c) { return client::use_as_container::iterator(&c, (int const*)0); } }; }}}
// All specializations of attribute customization points have to be placed into // the namespace boost::spirit::traits. namespace boost { namespace spirit { namespace traits { // The specialization of the template 'deref_iterator<>' will be used to // dereference the iterator associated with our counter data structure. template <> struct deref_iterator<client::use_as_container::iterator> { typedef client::use_as_container::type type; static type call(client::use_as_container::iterator const& it) { return *it.current_; } }; template <> struct next_iterator<client::use_as_container::iterator> { static void call(client::use_as_container::iterator& it) { if (it.current_ == &it.container_->value1_) it.current_ = &it.container_->value2_; else if (it.current_ == &it.container_->value2_) it.current_ = &it.container_->value3_; else it.current_ = 0; } }; template <> struct compare_iterators<client::use_as_container::iterator> { static bool call(client::use_as_container::iterator const& it1 , client::use_as_container::iterator const& it2) { return it1.current_ == it2.current_ && it1.container_ == it2.container_; } }; }}}
Последний фрагмент кода показывает пример, использующий экземпляр структуры данных<client::use_as_container
>для генерации вывода изСписка<%
>генератора:
client::use_as_container d2 (1, 2, 3); // use the instance of a 'client::use_as_container' instead of a STL vector std::cout << karma::format(karma::int_ % ", ", d2) << std::endl; // prints: '1, 2, 3'
Как вы можете видеть, специализации для точек настройки, как определено выше, обеспечивают бесшовную интеграцию пользовательской структуры данных без необходимости изменения формата вывода или самого генератора.
Статья Increment the Iterator pointing into a Container Attribute раздела Spirit 2.5.2 Extract Attribute Values to Generate Output from a Container (Karma) может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Extract Attribute Values to Generate Output from a Container (Karma) ::
реклама |