<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright 2012 Eric Niebler

  Distributed under the Boost
  Software License, Version 1.0. (See accompanying
  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  -->
<header name="boost/proto/transform/env.hpp">
  <namespace name="boost">
    <namespace name="proto">

      <struct name="key_not_found">
        <purpose>
          The type of objects returned when a key-based lookup fails in a
          transform environment.
        </purpose>
      </struct>

      <!-- empty_env -->
      <struct name="empty_env">
        <purpose>
          The type of an object that represents a transform environment
          with no key/value pairs in it.
        </purpose>

        <method-group name="public member functions">
          <method name="operator[]" cv="const">
            <type><classname>proto::key_not_found</classname></type>
            <parameter name="">
              <paramtype><replaceable>unspecified</replaceable></paramtype>
            </parameter>
            <description>
              <para>The type of the argument to this function has a
              user-defined implicit conversion from any type.</para>
            </description>
          </method>
        </method-group>
      </struct>

      <!-- env -->
      <struct name="env">
        <template>
          <template-type-parameter name="Key"/>
          <template-type-parameter name="Value"/>
          <template-type-parameter name="Env">
            <default><classname>proto::empty_env</classname></default>
          </template-type-parameter>
        </template>

        <constructor specifiers="explicit">
          <parameter name="value">
            <paramtype>Value const &amp;</paramtype>
            <description>
              <para>
                The value to be associated with the <code>Key</code>.
              </para>
            </description>
          </parameter>
          <parameter name="other">
            <paramtype>Env const &amp;</paramtype>
            <default>Env()</default>
            <description>
              <para>
                Another key/value store.
              </para>
            </description>
          </parameter>
        </constructor>

        <method-group name="public member functions">
          <method name="operator[]" cv="const">
            <type><replaceable>see-below</replaceable></type>
            <parameter name="">
              <paramtype><replaceable>see-below</replaceable></paramtype>
            </parameter>
            <description>
              <para>
                If called with an object that is implicitly convertible to type <code>Key</code>,
                this function returns the <code>Value</code> passed to the constructor. Otherwise, it returns
                the result of calling <code>operator[]</code> on the <code>Env</code> passed to
                the constructor.
              </para>
            </description>
          </method>
        </method-group>
      </struct>

      <!-- is_env -->
      <struct name="is_env">
        <template>
          <template-type-parameter name="T"/>
        </template>
        <inherit><type>mpl::bool_&lt;<replaceable>true-or-false</replaceable>&gt;</type></inherit>
        <purpose>
          <para>A Boolean metafuntion for determining whether or not a type is a Proto
          transform environment.</para>
        </purpose>
        <description>
          <para><code>is_env&lt;T&gt;</code> inherits from <code>mpl::true_</code> under the following
          conditions:
            <itemizedlist>
              <listitem>If <code>T</code> is <classname>proto::empty_env</classname>.</listitem>
              <listitem>If <code>T</code> is a specialization of <classname>proto::env&lt;&gt;</classname>.</listitem>
              <listitem>If <code>T</code> is derived from any of the above.</listitem>
              <listitem>If <code>T</code> is a cv-qualified variant of any of the above.</listitem>
              <listitem>If <code>T</code> is a reference to any of the above.</listitem>
            </itemizedlist>
          </para>
          <para>Otherwise, <code>is_env&lt;T&gt;</code> inherits from <code>mpl::false_</code>.
        </para>
        </description>
      </struct>

      <struct name="data_type">
        <purpose>
          The type of <code><globalname>proto::data</globalname></code>, a key for use when creating
          a transform environment that associates a piece of data with this type.
        </purpose>
        <description>
          <para>
            The <code>proto::data_type</code> type, along with the <code><globalname>proto::data</globalname></code>
            global, are declared using the <code><macroname>BOOST_PROTO_DEFINE_ENV_VAR</macroname>()</code> macro.
          </para>
        </description>
        <method-group name="public member functions">
          <overloaded-method name="operator=">
            <signature cv="const">
              <template>
                <template-type-parameter name="Value"/>
              </template>
              <type><classname>env</classname>&lt;data_type, <replaceable>see-below</replaceable>&gt;</type>
              <parameter name="value">
                <paramtype>Value &amp;</paramtype>
              </parameter>
            </signature>
            <signature cv="const">
              <template>
                <template-type-parameter name="Value"/>
              </template>
              <type><classname>env</classname>&lt;data_type, <replaceable>see-below</replaceable>&gt;</type>
              <parameter name="value">
                <paramtype>Value const &amp;</paramtype>
              </parameter>
            </signature>
            <description>
              <para>
                If <code>Value</code> is a specialization <code>boost::reference_wrapper&lt;T&gt;</code>,
                this function returns <code><classname>env</classname>&lt;data_type, T &amp;&gt;(value.get())</code>.
              </para>
              <para>
                Else, if the type <code>Value</code> is non-copyable (i.e., a function, an array, abstract, or an ostream),
                this function returns <code><classname>env</classname>&lt;data_type, Value <replaceable>cv</replaceable> &amp;&gt;(value)</code>,
                where <code><replaceable>cv</replaceable></code> is <code>const</code> for the second overload, and empty
                for the first.
              </para>
              <para>
                Otherwise, this function returns <code><classname>env</classname>&lt;data_type, Value&gt;(value)</code>.
              </para>
            </description>
          </overloaded-method>
        </method-group>
      </struct>

      <data-member name="data">
        <description>
          <para>A key used for creating a transform environment.</para>
        </description>
        <type><classname>proto::data_type</classname> const</type>
      </data-member>
      
      <namespace name="functional">

        <!-- functional::as_env -->
        <struct name="as_env">
          <inherit><classname>proto::callable</classname></inherit>
          <purpose>
            A unary <conceptname>PolymorphicFunctionObject</conceptname> for ensuring that an object
            is a transform environment. If it isn't already, it is turned into one such that the
            object is associated with the <classname>proto::data_type</classname> key.
          </purpose>
          <struct name="result">
            <template>
              <template-type-parameter name="Sig"/>
            </template>
            <typedef name="type">
              <type><replaceable>see-below</replaceable></type>
              <description>
                <para>See <code><methodname>proto::functional::as_env::operator()</methodname></code>.</para>
              </description>
            </typedef>
            <description>
              <para>
                Encodes the return type of <code><methodname>proto::functional::as_env::operator()</methodname></code>.
                The presence of this member template makes <code><classname>proto::functional::as_env</classname></code>
                a valid TR1-style function object type usable with <code>boost::result_of&lt;&gt;</code>.
              </para>
            </description>
          </struct>
          <method-group name="public member functions">
            <overloaded-method name="operator()">
              <signature cv="const">
                <template>
                  <template-type-parameter name="T"/>
                </template>
                <type><replaceable>see-below</replaceable></type>
                <parameter name="t">
                  <paramtype>T &amp;</paramtype>
                </parameter>
              </signature>
              <signature cv="const">
                <template>
                  <template-type-parameter name="T"/>
                </template>
                <type><replaceable>see-below</replaceable></type>
                <parameter name="t">
                  <paramtype>T const &amp;</paramtype>
                </parameter>
              </signature>
              <description>
                <para>
                  If <code><classname>proto::is_env</classname>&lt;T&gt;::value</code> is <code>false</code>,
                  this function returns the result of <code>(<globalname>proto::data</globalname> = t)</code>.
                  See <code><methodname>proto::data_type::operator=</methodname></code> for details.
                </para>
                <para>
                  Otherwise, this function returns <code>t</code> by reference.
                </para>
              </description>
            </overloaded-method>
          </method-group>
        </struct>

        <!-- functional::has_env_var -->
        <struct name="has_env_var">
          <inherit><classname>proto::callable</classname></inherit>
          <template>
            <template-type-parameter name="Key"/>
          </template>
          <purpose>
            A unary boolean <conceptname>PolymorphicFunctionObject</conceptname> used for determining whether a particular
            transform environment has a value associated with a particular key.
          </purpose>
          <struct name="result">
            <template>
              <template-type-parameter name="Sig"/>
            </template>
            <typedef name="type">
              <type><replaceable>see-below</replaceable></type>
              <description>
                <para>See <code><methodname>proto::functional::has_env_var::operator()</methodname></code>.</para>
              </description>
            </typedef>
            <description>
              <para>
                Encodes the return type of <code><methodname>proto::functional::has_env_var::operator()</methodname></code>.
                The presence of this member template makes <code><classname>proto::functional::has_env_var</classname></code>
                a valid TR1-style function object type usable with <code>boost::result_of&lt;&gt;</code>.
              </para>
            </description>
          </struct>
          <method-group name="public member functions">
            <method name="operator()" cv="const">
              <template>
                <template-type-parameter name="Env"/>
              </template>
              <type><replaceable>see-below</replaceable></type>
              <parameter name="e">
                <paramtype>Env const &amp;</paramtype>
              </parameter>
              <description>
                <para>
                  This function behaves as follows:
                  <itemizedlist>
                    <listitem>
                      If <code><classname>proto::is_env</classname>&lt;Env&gt;::value</code> is <code>true</code>:
                      <itemizedlist>
                        <listitem>
                          If <code>e[Key()]</code> returns an instance of
                          <code><classname>proto::key_not_found</classname></code>, return
                          <code>mpl::false_</code>. See <code><methodname>proto::env::operator[]</methodname></code>
                          for more information.
                        </listitem>
                        <listitem>
                          Otherwise, return <code>mpl::true_</code>.
                        </listitem>
                      </itemizedlist>
                    </listitem>
                    <listitem>
                      Otherwise:
                      <itemizedlist>
                        <listitem>
                          If <code>Key</code> is <code><classname>proto::data_type</classname></code>,
                          return <code>mpl::true_</code>.
                        </listitem>
                        <listitem>
                          Otherwise, return <code>mpl::false_</code>.
                        </listitem>
                      </itemizedlist>
                    </listitem>
                  </itemizedlist>
                </para>
              </description>
            </method>
          </method-group>
        </struct>
        
        <!-- functional::env_var -->
        <struct name="env_var">
          <inherit><classname>proto::callable</classname></inherit>
          <template>
            <template-type-parameter name="Key"/>
          </template>
          <purpose>
            A unary <conceptname>PolymorphicFunctionObject</conceptname> used for fetching the value 
            associated with a particular key in a transform environment.
          </purpose>
          <struct name="result">
            <template>
              <template-type-parameter name="Sig"/>
            </template>
            <typedef name="type">
              <type><replaceable>see-below</replaceable></type>
              <description>
                <para>See <code><methodname>proto::functional::env_var::operator()</methodname></code>.</para>
              </description>
            </typedef>
            <description>
              <para>
                Encodes the return type of <code><methodname>proto::functional::env_var::operator()</methodname></code>.
                The presence of this member template makes <code><classname>proto::functional::env_var</classname></code>
                a valid TR1-style function object type usable with <code>boost::result_of&lt;&gt;</code>.
              </para>
            </description>
          </struct>
          <method-group name="public member functions">
            <method name="operator()" cv="const">
              <template>
                <template-type-parameter name="Env"/>
              </template>
              <type><replaceable>see-below</replaceable></type>
              <parameter name="e">
                <paramtype>Env const &amp;</paramtype>
              </parameter>
              <description>
                <para>
                  This function behaves as follows:
                  <itemizedlist>
                    <listitem>
                      If <code>Key</code> is <code><classname>proto::data_type</classname></code>:
                      <itemizedlist>
                        <listitem>
                          If <code><classname>proto::is_env</classname>&lt;Env&gt;::value</code> is <code>true</code>,
                          return <code>e[<globalname>proto::data</globalname>]</code>.
                        </listitem>
                        <listitem>
                          Otherwise, return <code>e</code>.
                        </listitem>
                      </itemizedlist>
                    </listitem>
                    <listitem>
                      Otherwise, return <code>e[Key()]</code>.
                    </listitem>
                  </itemizedlist>
                </para>
                <para>
                  See <code><methodname>proto::env::operator[]</methodname></code> for additional information.
                </para>
              </description>
            </method>
          </method-group>
        </struct>
        
      </namespace>

      <namespace name="result_of">
        <struct name="as_env">
          <template>
            <template-type-parameter name="T"/>
          </template>
          <inherit><type>boost::result_of&lt;<classname>proto::functional::as_env</classname>(T)&gt;</type></inherit>
          <purpose>
            Metafunction for computing the return type of <code><functionname>proto::as_env()</functionname></code>.
          </purpose>
        </struct>
        <struct name="has_env_var">
          <template>
            <template-type-parameter name="Env"/>
            <template-type-parameter name="Key"/>
          </template>
          <inherit><type>boost::result_of&lt;<classname>proto::functional::has_env_var</classname>&lt;Key&gt;(Env)&gt;::type</type></inherit>
          <purpose>
            Metafunction for computing the return type of <code><functionname>proto::has_env_var()</functionname></code>.
          </purpose>
        </struct>
        <struct name="env_var">
          <template>
            <template-type-parameter name="Env"/>
            <template-type-parameter name="Key"/>
          </template>
          <inherit><type>boost::result_of&lt;<classname>proto::functional::env_var</classname>&lt;Key&gt;(Env)&gt;</type></inherit>
          <purpose>
            Metafunction for computing the return type of <code><functionname>proto::env_var()</functionname></code>.
          </purpose>
        </struct>
      </namespace>

      <!-- proto::as_env -->
      <overloaded-function name="as_env">
        <signature>
          <template>
            <template-type-parameter name="T"/>
          </template>
          <type>typename <classname>proto::result_of::as_env</classname>&lt;T &amp;&gt;::type</type>
          <parameter name="t">
            <paramtype>T &amp;</paramtype>
          </parameter>
        </signature>
        <signature>
          <template>
            <template-type-parameter name="T"/>
          </template>
          <type>typename <classname>proto::result_of::as_env</classname>&lt;T const &amp;&gt;::type</type>
          <parameter name="t">
            <paramtype>T const &amp;</paramtype>
          </parameter>
        </signature>
        <purpose>
          For ensuring that the given argument is a transform environment. If it is not already,
          it is made one as if by <code>(<globalname>proto::data</globalname> = t)</code>.
        </purpose>
        <description>
          <para>
            See also:
            <itemizedlist>
              <listitem>
                <code><methodname>proto::data_type::operator=</methodname></code>
              </listitem>
              <listitem>
                <code><methodname>proto::functional::as_env::operator()</methodname></code>
              </listitem>
            </itemizedlist>
          </para>
        </description>
        <returns><code><classname>proto::functional::as_env</classname>()(t)</code></returns>
      </overloaded-function>
      
      <!-- proto::has_env_var -->
      <overloaded-function name="has_env_var">
        <signature>
          <template>
            <template-type-parameter name="Key"/>
            <template-type-parameter name="Env"/>
          </template>
          <type>typename <classname>proto::result_of::has_env_var</classname>&lt;Env &amp;, Key&gt;::type</type>
          <parameter name="e">
            <paramtype>Env &amp;</paramtype>
          </parameter>
        </signature>
        <signature>
          <template>
            <template-type-parameter name="Key"/>
            <template-type-parameter name="Env"/>
          </template>
          <type>typename <classname>proto::result_of::has_env_var</classname>&lt;Env const &amp;, Key&gt;::type</type>
          <parameter name="e">
            <paramtype>Env const &amp;</paramtype>
          </parameter>
        </signature>
        <purpose>
          For testing to see whether a value exists in a transform environment corresponding to the
          specified <code>Key</code>.
        </purpose>
        <description>
          <para>
            See also:
            <itemizedlist>
              <listitem>
                <code><methodname>proto::functional::has_env_var::operator()</methodname></code>
              </listitem>
            </itemizedlist>
          </para>
        </description>
        <returns><code><classname>proto::functional::has_env_var&lt;Key&gt;</classname>()(e)</code></returns>
      </overloaded-function>

      <!-- proto::env_var -->
      <overloaded-function name="env_var">
        <signature>
          <template>
            <template-type-parameter name="Key"/>
            <template-type-parameter name="Env"/>
          </template>
          <type>typename <classname>proto::result_of::env_var</classname>&lt;Env &amp;, Key&gt;::type</type>
          <parameter name="e">
            <paramtype>Env &amp;</paramtype>
          </parameter>
        </signature>
        <signature>
          <template>
            <template-type-parameter name="Key"/>
            <template-type-parameter name="Env"/>
          </template>
          <type>typename <classname>proto::result_of::env_var</classname>&lt;Env const &amp;, Key&gt;::type</type>
          <parameter name="e">
            <paramtype>Env const &amp;</paramtype>
          </parameter>
        </signature>
        <purpose>
          For fetching the value from a transform environment corresponding to the
          specified <code>Key</code>.
        </purpose>
        <description>
          <para>
            See also:
            <itemizedlist>
              <listitem>
                <code><methodname>proto::functional::env_var::operator()</methodname></code>
              </listitem>
            </itemizedlist>
          </para>
        </description>
        <returns><code><classname>proto::functional::env_var&lt;Key&gt;</classname>()(e)</code></returns>
      </overloaded-function>

      <!-- proto::operator, -->
      <overloaded-function name="operator,">
        <signature>
          <template>
            <template-type-parameter name="Env"/>
            <template-type-parameter name="Key"/>
            <template-type-parameter name="Value"/>
          </template>
          <type><classname>proto::env</classname>&lt;Key, Value, <replaceable>UNCVREF</replaceable>(typename <classname>proto::result_of::as_env</classname>&lt;Env &amp;&gt;::type)&gt;</type>
          <parameter name="other">
            <paramtype>Env &amp;</paramtype>
          </parameter>
          <parameter name="head">
            <paramtype><classname>proto::env</classname>&lt;Key, Value&gt; const &amp;</paramtype>
          </parameter>
        </signature>
        <signature>
          <template>
            <template-type-parameter name="Env"/>
            <template-type-parameter name="Key"/>
            <template-type-parameter name="Value"/>
          </template>
          <type><classname>proto::env</classname>&lt;Key, Value, <replaceable>UNCVREF</replaceable>(typename <classname>proto::result_of::as_env</classname>&lt;Env const &amp;&gt;::type)&gt;</type>
          <parameter name="other">
            <paramtype>Env const &amp;</paramtype>
          </parameter>
          <parameter name="head">
            <paramtype><classname>proto::env</classname>&lt;Key, Value&gt; const &amp;</paramtype>
          </parameter>
        </signature>
        <purpose>
          For composing a larger transform environment from two smaller ones.
        </purpose>
        <description>
          <para>
            The effect of this function is to take two transform environments and compose them into
            a larger environment that contains the key/values pairs of the two. The first argument
            is allowed to not be a transform environment, in which case it is turned into one with
            the <functionname>proto::as_env()</functionname> function before composition with the
            second argument. The second argument is required to be a transform environment with exactly
            one key/value pair.
          </para>
          <para>
            <emphasis role="bold">Example:</emphasis>
          </para>
          <para>
            Given user-defined keys <code>key0</code> and <code>key1</code> of types <code>key0_type</code>
            and <code>key1_type</code>, the following code demonstrates how the chained use of <code>operator,</code>
            can build a composite transform environment containing a number of key/value pairs:
            <programlisting><classname>proto::env</classname>&lt;
    key1_type
  , int
  , <classname>proto::env</classname>&lt;
        key0_type
      , char const (&amp;)[6]
      , <classname>proto::env</classname>&lt;<classname>proto::data_type</classname>, int&gt;
    &gt;
&gt; myenv = (<globalname>proto::data</globalname> = 1, key0 = "hello", key1 = 42);
// NOTE: operator, here --^    and here --^

// Check the results:
assert(1 == myenv[proto::data]);
assert(0 == std::strcmp(myenv[key0], "hello"));
assert(42 == myenv[key1]);</programlisting>
          </para>
          <para>
            <emphasis role="bold">Note:</emphasis> In the return type and the "Returns" clause, <code><replaceable>UNCVREF</replaceable>(X)</code> is
            the type <code>X</code> stripped of top-level reference and cv-qualifiers.
          </para>
          <para>
            <emphasis role="bold">Note:</emphasis> In the "Returns" clause, <code><replaceable>cv</replaceable></code> is replaced with <code>const</code>
            for the second overload, and nothing for the first.
          </para>
          <para>
            <emphasis role="bold">See also:</emphasis>
            <itemizedlist>
              <listitem>
                <code><methodname>proto::env::operator[]</methodname></code>
              </listitem>
            </itemizedlist>
          </para>
        </description>
        <returns><code><classname>proto::env</classname>&lt;Key, Value, <replaceable>UNCVREF</replaceable>(typename <classname>proto::result_of::as_env</classname>&lt;Env <replaceable>cv</replaceable> &amp;&gt;::type)&gt;(head[Key()], <functionname>proto::as_env</functionname>(other))</code></returns>
      </overloaded-function>

      <!-- struct _env_var -->
      <struct name="_env_var">
        <template>
          <template-type-parameter name="Key"/>
        </template>
        <purpose>
          A primitive transform that returns the value associated with a particular <code>Key</code>
          in the current transform environment.
        </purpose>
        <inherit>
          <type><classname>proto::transform</classname>&lt;_env_var&lt;Key&gt; &gt;</type>
        </inherit>
        <struct name="impl">
          <template>
            <template-type-name name="Expr"/>
            <template-type-name name="State"/>
            <template-type-name name="Data"/>
          </template>
          <inherit>
            <type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt; &gt;</type>
          </inherit>
          <typedef name="result_type">
            <type>typename <classname>proto::result_of::env_var</classname>&lt;Data, Key&gt;::type</type>
          </typedef>
          <method-group name="public member functions">
            <method name="operator()" cv="const">
              <type>result_type</type>
              <parameter name="">
                <paramtype>typename impl::expr_param</paramtype>
              </parameter>
              <parameter name="">
                <paramtype>typename impl::state_param</paramtype>
              </parameter>
              <parameter name="data">
                <paramtype>typename impl::data_param</paramtype>
                <description>
                  <para>The current transform environment</para>
                </description>
              </parameter>
              <description>
                <para>
                  Fetches the value associated with <code>Key</code> from the transform environment
                  passed in the data (third) parameter.
                </para>
              </description>
              <requires>
                <para>
                  <code><classname>proto::is_env</classname>&lt;Data&gt;::value</code>
                  is <code>true</code>.
                </para>
              </requires>
              <returns>
                <para>
                  <code><functionname>proto::env_var</functionname>(data)</code>
                </para>
              </returns>
            </method>
          </method-group>
        </struct>
        <description>
          <para>
            See <code><classname>proto::_env_var::impl</classname></code> for the full details.
          </para>
        </description>
      </struct>
      
      <!-- struct _env -->
      <struct name="_env">
        <purpose>
          A primitive transform that returns the current transform environment unmodified.
        </purpose>
        <inherit>
          <type><classname>proto::transform</classname>&lt;_env&gt;</type>
        </inherit>
        <struct name="impl">
          <template>
            <template-type-name name="Expr"/>
            <template-type-name name="State"/>
            <template-type-name name="Data"/>
          </template>
          <inherit>
            <type><classname>proto::transform_impl</classname>&lt;Expr, State, Data&gt;</type>
          </inherit>
          <typedef name="result_type">
            <type>Data</type>
          </typedef>
          <method-group name="public member functions">
            <method name="operator()" cv="const">
              <type>result_type</type>
              <parameter name="">
                <paramtype>typename impl::expr_param</paramtype>
              </parameter>
              <parameter name="">
                <paramtype>typename impl::state_param</paramtype>
              </parameter>
              <parameter name="data">
                <paramtype>typename impl::data_param</paramtype>
                <description>
                  <para>The current transform environment </para>
                </description>
              </parameter>
              <description>
                <para>
                  Returns the current transform environment
                  passed in the data (third) parameter.
                </para>
              </description>
              <returns>
                <para>
                  <code>data</code>
                </para>
              </returns>
            </method>
          </method-group>
        </struct>
        <description>
          <para>
            See <code><classname>proto::_env::impl</classname></code> for the full details.
          </para>
        </description>
      </struct>
    </namespace>
  </namespace>

  <!-- BOOST_PROTO_DEFINE_ENV_VAR() -->
  <macro name="BOOST_PROTO_DEFINE_ENV_VAR" kind="functionlike">
    <macro-parameter name="Type"/>
    <macro-parameter name="Name"/>
    <purpose>
      Define a type and a global variable of that type that can be used
      to initialize a slot in a Proto transform environment.
    </purpose>
    <description>
      <para>
        Proto primitive transforms can optionally accept an environment in
        their third parameter which is a key/value store of environment
        variables. Use the <code>BOOST_PROTO_DEFINE_ENV_VAR()</code> macro
        to define the keys.
      </para>
      <para>
        See the description for <code><classname alt="boost::proto::data_type">proto::data_type</classname></code>
        for an example of the class interface created by this macro.
      </para>
      <para>
        <emphasis role="bold">Example:</emphasis>
      </para>
      <para>
        <programlisting>BOOST_PROTO_DEFINE_ENV_VAR(mykey_type, mykey);

struct FetchMyKey
  : <classname alt="boost::proto::when">proto::when</classname>&lt; <classname alt="boost::proto::_">_</classname>, <classname alt="boost::proto::_env_var">proto::_env_var</classname>&lt;mykey_type&gt; &gt;
{};

int main()
{
    <classname alt="boost::proto::terminal">proto::terminal</classname>&lt;int&gt;::type i = {42};
    char const * sz = FetchMyKey()(i, 0, (mykey = "hello!"));
    assert(0 == std::strcmp(sz, "hello!");
}</programlisting>
      </para>
    </description>

  </macro>

</header>
