Customization of Spirit's Attribute Handling

| Home | Libraries | People | FAQ | More

### Customization of Spirit's Attribute Handling

##### Why do we need Attribute Customization Points

| Important
Before you read on please be aware that the interfaces described in this section are not finalized and may change in the future without attempting to be backwards compatible. We document the customization point interfaces anyways as we think they are important. Understanding customization points helps understanding Spirit. Additionally they prove to be powerful tools enabling full integration of the user's data structures with Qi's parsers and Karma's generators.

Spirit has been written with extensibility in mind. It provides many different attribute customization points allowing to integrate custom data types with the process of parsing in Spirit.Qi or output generation with Spirit.Karma. All attribute customization points are exposed using a similar technique: full or partial template specialization. Spirit generally implements the main template, providing a default implementation. You as the user have to provide a partial or full specialization of this template for the data types you want to integrate with the library. In fact, the library uses these customization points itself for instance to handle the magic of the `unused_type` attribute type.

Here is an example showing the `container_value` customization point used by different parsers (such as Kleene, Plus, etc.) to find the attribute type to be stored in a supplied STL container:

    template <typename Container, typename Enable/* = void*/>
    struct container_value
      : detail::remove_value_const<typename Container::value_type>
    {};

This template is instantiated by the library at the appropriate places while using the supplied container type as the template argument. The embedded `type` is used as the attribute type while parsing the elements to be store in that container.

The following example shows the predefined specialization for `unused_type`:

    template <>
    struct container_value<unused_type>
    {
        typedef unused_type type;
    };

which defines its embedded `type` to be `unused_type` as well, this way propagating the 'don't care' attribute status to the embedded parser.

All attribute customization points follow the same scheme. The last template parameter is always `typename Enable = void` allowing to apply SFINAE for fine grained control over the template specialization process. But most of the time you can safely forget about its existence.

The following sections will describe all customization points, together with a description which needs to be specialized for what purpose.

##### The Usage of Customization Points

The different customizations points are used by different parts of the library. Part of the customizations points are used by both, Spirit.Qi and Spirit.Karma, whereas others are specialized to be applied for one of the sub-libraries only. We will explain when a specific customization point needs to be implemented and, equally important, which customization points need to be implemented at the same time. Often it is not sufficient to provide a specialization for one single customization point only, in this case you as the user have to provide all necessary customizations for your data type you want to integrate with the library.