Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext
Dereference the Iterator pointing into a Container Attribute
deref_iterator

The template deref_iterator is a type used as an attribute customization point. It is invoked by the Karma repetitive generators (such as List (%), Kleene (unary *), Plus (unary +), and Repeat) in order to dereference an iterator pointing to an element of a container holding the attributes to generate output from.

Module Headers
#include <boost/spirit/home/support/container.hpp>

Also, see Include Structure.

[Note] Note

This header file does not need to be included directly by any user program as it is normally included by other Spirit header files relying on its content.

Namespace

Name

boost::spirit::traits

Synopsis
template <typename Iterator, typename Enable>
struct deref_iterator
{
    typedef <unspecified> type;
    static type call(Iterator& it);
};
Template parameters

Parameter

Description

Default

Iterator

The type, Iterator of the iterator to dereference. This is the same as the type returned by the customization point traits::container_iterator.

none

Enable

Helper template parameter usable to selectively enable or disable certain specializations of deref_iterator utilizing SFINAE (i.e. boost::enable_if or boost::disable_if).

void

Notation

Iterator

An iterator type.

it

An instance of an iterator of type Iterator.

C

A container type whose iterator type is Iterator.

Expression Semantics

Expression

Semantics

deref_iterator<Iterator>::type

Metafunction result evaluating to the type returned by dereferencing the iterator.

deref_iterator<Iterator>::call(it)

Return the element in the container referred to by the iterator. The type of the returned value is the same as returned by the metafunction result type.

Predefined Specializations

Spirit predefines specializations of this customization point for several types. The following table lists those types together with the types returned by the embedded typedef type:

Template Parameters

Semantics

Iterator

The metafunction result type evaluates to std::iterator_traits<Iterator>::reference and the function call() returns *it.

unused_type const*

The metafunction result type evaluates to unused_type and the function call() returns unused.

When to implement

The customization point deref_iterator needs to be implemented for a specific iterator type whenever the container this iterator belongs to is to be used as an attribute in place of a STL container. It is applicable for generators (Spirit.Karma) only. As a rule of thumb: it has to be implemented whenever a certain iterator type belongs to a container which is to be passed as an attribute to a generator normally exposing a STL container, C and if the container type does not expose the interface of a STL container (i.e. is_container<C>::type would normally return mpl::false_).

Related Attribute Customization Points

If this customization point is implemented, the following other customization points might need to be implemented as well.

Name

When to implement

traits::is_container

Needs to be implemented whenever a type is to be used as a container attribute in Karma.

traits::container_iterator

Karma: List (%), Kleene (unary *), Plus (unary +), Repeat.

traits::begin_container

Karma: List (%), Kleene (unary *), Plus (unary +), Repeat.

traits::end_container

Karma: List (%), Kleene (unary *), Plus (unary +), Repeat.

traits::deref_iterator

Karma: List (%), Kleene (unary *), Plus (unary +), Repeat.

traits::next_iterator

Karma: List (%), Kleene (unary *), Plus (unary +), Repeat.

traits::compare_iterators

Karma: List (%), Kleene (unary *), Plus (unary +), Repeat.

Example

Here are the header files needed to make the example code below compile:

#include <boost/spirit/include/karma.hpp>
#include <iostream>
#include <vector>

The example (for the full source code please see here: customize_counter.cpp) uses the data structure

namespace client
{
    struct counter
    {
        // expose the current value of the counter as our iterator
        typedef int iterator;

        // expose 'int' as the type of each generated element
        typedef int type;

        counter(int max_count)
          : counter_(0), max_count_(max_count)
        {}

        int counter_;
        int max_count_;
    };
}

as a direct attribute to the List (%) generator. This type does not expose any of the interfaces of an STL container. It does not even expose the usual semantics of a container. The presented customization points build a counter instance which is incremented each time it is accessed. The examples shows how to enable its use as an attribute to Karma's repetitive generators.

In order to make this data structure compatible we need to specialize a couple of attribute customization points: traits::is_container, traits::container_iterator, traits::begin_container, and traits::end_container. In addition, we specialize one of the iterator related customization points as well: traits::deref_iterator.

// 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::counter' as a container providing 
    // the items to generate output from.
    template <>
    struct is_container<client::counter 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. 
    template <>
    struct container_iterator<client::counter const>
    {
        typedef client::counter::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. 
    // These specializations respectively return the initial and maximum 
    // counter values.
    //
    // The passed argument refers to the attribute instance passed to the list 
    // generator.
    template <>
    struct begin_container<client::counter const>
    {
        static client::counter::iterator
        call(client::counter const& c)
        {
            return c.counter_;
        }
    };

    template <>
    struct end_container<client::counter const>
    {
        static client::counter::iterator
        call(client::counter const& c)
        {
            return c.max_count_;
        }
    };
}}}

// 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.
    // Since we expose the current value as the iterator we just return the 
    // current iterator as the return value.
    template <>
    struct deref_iterator<client::counter::iterator>
    {
        typedef client::counter::type type;

        static type call(client::counter::iterator const& it)
        {
            return it;
        }
    };
}}}

The last code snippet shows an example using an instance of the data structure client::counter to generate output from a List (%) generator:

// use the instance of a 'client::counter' instead of a STL vector
client::counter count(4);
std::cout << karma::format(karma::int_ % ", ", count) << std::endl;   // prints: '0, 1, 2, 3'

As you can see, the specializations for the customization points as defined above enable the seamless integration of the custom data structure without having to modify the output format or the generator itself.

For other examples of how to use the customization point deref_iterator please see here: use_as_container.


PrevUpHomeNext