| Home | Libraries | People | FAQ | More

#### Transform an Attribute to a Different Type (Qi and Karma)

###### transform_attribute

The template `transform_attribute` is a type used as an attribute customization point. It is invoked by Qi `rule`, semantic action and `attr_cast`, and Karma `rule`, semantic action and `attr_cast`. It is used to automatically transform the user provided attribute to the attribute type expected by the right hand side component (for `rule`), the semantic action, or the embedded component (for `attr_cast`).

| Note
The interface of this customization point has been changed with Boost V1.44. We added the `Domain` template parameter to allow for more fine grained specializations for Spirit.Qi and Spirit.Karma.

###### Module Headers

    #include <boost/spirit/home/support/attributes.hpp>

Also, see Include Structure.

| 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 Exposed, typename Transformed, typename Domain, typename Enable>
    struct transform_attribute
    {
        typedef <unspecified> type;

        static type pre(Exposed& val);
        static void post(Exposed& val, type attr);    // Qi only
        static void fail(Exposed&);                   // Qi only
    };

###### Template parameters

Parameter | Description | Default
--- | --- | ---
`Exposed` | The attribute type supplied to the component which needs to be transformed. | none
`Transformed` | The attribute type expected by the component to be provided as the result of the transformation. | none
`Domain` | The domain of the sub library the template is instantiated in. Typically this is either `qi::domain` or `karma::domain`. | none
`Enable` | Helper template parameter usable to selectively enable or disable certain specializations of `transform_attribute` utilizing SFINAE (i.e. `boost::enable_if` or `boost::disable_if`). | `void`

Notation

`Exposed`

  The type, `Exposed` is the type of the attribute as passed in by the user.

`Transformed`

  The type, `Transformed` is the type of the attribute as passed along to the right hand side of the `rule` (embedded component of `attr_cast`).

`Domain`

  The domain of the sub library the template is instantiated in. Typically this is either `qi::domain` or `karma::domain`.

`exposed`

  An instance of type `Exposed`.

`transformed`

  An instance of type `Transformed`.

###### Expression Semantics

Expression | Semantics
--- | ---
`transform_attribute<Exposed, Transformed, Domain>::type` | Evaluates to the type to be used as the result of the transformation (to be passed to the right hand side of the `rule` or to the embedded component of the `attr_cast`. Most of the time this is equal to `Transformed`, but in other cases this might evaluate to `Transformed&` instead avoiding superfluous object creation.

    type transform_attribute<Exposed, Transformed, Domain>::pre(exposed)

Do `pre`-transformation before invoking the right hand side component for `rule` (or the embedded component for `attr_cast`). This takes the attribute supplied as by the user (of type `Exposed`) and returns the attribute to be passed down the component hierarchy (of the type as exposed by the metafunction `type`). This function will be called in Qi and for Karma.

    void transform_attribute<Exposed, Transformed, Domain>::post(exposed, transformed)

Do `post`-transformation after the invocation of the right hand side component for `rule` (or the embedded component for `attr_cast`). This takes the original attribute as supplied by the user and the attribute as returned from the right hand side (embedded) component and is expected to propagate the result back into the supplied attribute instance. This function will be called in Qi only.

    void transform_attribute<Exposed, Transformed, Domain>::fail(exposed)

Handling failing parse operations of the right hand side component for `rule` (or the embedded component for `attr_cast`). This function will be called in Qi only.

###### Predefined Specializations

Template parameters | Semantics
--- | ---
`Exposed`, `Transformed` | `type` evaluates to `Transformed`, `pre()` returns a new instance of `Transformed` constructed from the argument of type `Exposed`, `post()` assigns `transformed` to `exposed`.

`optional<Exposed>`, `Transformed`, `typename disable_if<is_same<optional<Exposed>, Transformed> >::type`

`type` evaluates to `Transformed&`, `pre()` returns a reference to the instance of `Transformed` stored in the passed optional (the argument of type `optional<Exposed>`), the optional instance is initialized, if needed. `post()` does nothing, `fail()` resets the optional (its parameter) instance to the non-initialized state.

`Exposed&`, `Transformed` | `type` evaluates to `Transformed`, `pre()` returns a new instance of `Transformed` constructed from the argument of type `Exposed`, `post()` assigns `transformed` to `exposed`.
`Attrib&`, `Attrib` | `type` evaluates to `Attrib&`, `pre()` returns it's argument, `post()` does nothing.
`Exposed const`, `Transformed` | (usind in Karma only) `type` evaluates to `Transformed`, `pre()` returns it's argument, `post()` is not implemented.
`Attrib const&`, `Attrib` | (usind in Karma only) `type` evaluates to `Attrib const&`, `pre()` returns it's argument, `post()` is not implemented.
`Attrib const`, `Attrib` | (usind in Karma only) `type` evaluates to `Attrib const&`, `pre()` returns it's argument, `post()` is not implemented.
`unused_type`, `Attrib` | `type` evaluates to `unused_type`, `pre()` and `post()` do nothing.
`Attrib`, `unused_type` | `type` evaluates to `unused_type`, `pre()` and `post()` do nothing.

###### When to implement

The customization point `transform_attribute` needs to be implemented for a specific pair of types whenever the attribute type supplied to a `rule` or `attr_cast` cannot automatically transformed to the attribute type expected by the right hand side of the `rule` (embedded component of the `attr_cast`) because the default implementation as shown above is not applicable. Examples for this could be that the type `Transformed` is not constructible from the type `Exposed`.