<?xml version="1.0" encoding="utf-8"?>
<header name="boost/proto/make_expr.hpp">
  <para>
    Definition of the <computeroutput><functionname alt="boost::proto::make_expr">proto::make_expr()</functionname>
    </computeroutput> and <computeroutput><functionname alt="boost::proto::unpack_expr">proto::unpack_expr()</functionname>
    </computeroutput> utilities for building Proto expression nodes from child nodes or from a Fusion sequence of child
    nodes, respectively.
  </para>
  <namespace name="boost">
    <namespace name="proto">
      <namespace name="functional">
        <!-- proto::functional::make_expr -->
        <struct name="make_expr">
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Domain">
              <default><classname>proto::deduce_domain</classname></default>
            </template-type-parameter>
          </template>
          <purpose>A <conceptname>PolymorphicFunctionObject</conceptname> equivalent to the <computeroutput>
            <functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput> function.</purpose>
          <description>
            <para>
              In all cases, <computeroutput>proto::functional::make_expr&lt;Tag, Domain&gt;()(a...)</computeroutput>
              is equivalent to <computeroutput><functionname>proto::make_expr</functionname>&lt;Tag, Domain&gt;(a...)</computeroutput>.
            </para>
            <para>
              <computeroutput>proto::functional::make_expr&lt;Tag&gt;()(a...)</computeroutput> is equivalent to
              <computeroutput><functionname>proto::make_expr</functionname>&lt;Tag&gt;(a...)</computeroutput>.
            </para>
          </description>
          <inherit>
            <type><classname>proto::callable</classname></type>
          </inherit>
          <struct-specialization name="result">
            <template>
              <template-type-parameter name="This"/>
              <template-type-parameter name="A" pack="1"/>
            </template>
            <specialization>
              <template-arg>This(A...)</template-arg>
            </specialization>
            <inherit>
              <type>
    <classname>proto::result_of::make_expr</classname>&lt; Tag, Domain, A... &gt;</type>
            </inherit>
          </struct-specialization>
          <method-group name="public member functions">
            <method name="operator()" cv="const">
              <type>typename <classname>proto::result_of::make_expr</classname>&lt; Tag, Domain, A const... &gt;::type const</type>
              <template>
                <template-type-parameter name="A" pack="1"/>
              </template>
              <parameter name="a" pack="1">
                <paramtype>A const &amp;</paramtype>
              </parameter>
              <description>
                <para>
                  Construct an expression node with tag type <computeroutput>Tag</computeroutput> and in the 
                  domain <computeroutput>Domain</computeroutput>.
                </para>
                <para>
                </para>
              </description>
              <returns>
                <para>
                  <computeroutput><functionname>proto::make_expr</functionname>&lt;Tag, Domain&gt;(a...)</computeroutput>
                </para>
              </returns>
            </method>
          </method-group>
        </struct>
        
        <!-- proto::functional::unpack_expr -->
        <struct name="unpack_expr">
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Domain">
              <default><classname>proto::deduce_domain</classname></default>
            </template-type-parameter>
          </template>
          <purpose>A <conceptname>PolymorphicFunctionObject</conceptname> equivalent to the 
            <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput> function.
          </purpose>
          <description>
            <para>
              In all cases, <computeroutput>proto::functional::unpack_expr&lt;Tag, Domain&gt;()(seq)</computeroutput> is
              equivalent to <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname>&lt;Tag,
              Domain&gt;(seq)</computeroutput>.
            </para>
            <para>
              <computeroutput>proto::functional::unpack_expr&lt;Tag&gt;()(seq)</computeroutput> is equivalent to
              <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname>&lt;Tag&gt;(seq)</computeroutput>.
            </para>
          </description>
          <inherit>
            <type><classname>proto::callable</classname></type>
          </inherit>
          <struct-specialization name="result">
            <template>
              <template-type-parameter name="This"/>
              <template-type-parameter name="Sequence"/>
            </template>
            <specialization>
              <template-arg>This(Sequence)</template-arg>
            </specialization>
            <inherit>
              <type>
    <classname>proto::result_of::unpack_expr</classname>&lt;
      Tag,
      Domain,
      typename boost::remove_reference&lt; Sequence &gt;::type
    &gt;</type>
            </inherit>
          </struct-specialization>
          <method-group name="public member functions">
            <method name="operator()" cv="const">
              <type>typename <classname>proto::result_of::unpack_expr</classname>&lt; Tag, Domain, Sequence const &gt;::type const</type>
              <template>
                <template-type-parameter name="Sequence"/>
              </template>
              <parameter name="sequence">
                <paramtype>Sequence const &amp;</paramtype>
                <description>
                  <para>A Fusion Random Access Sequence </para>
                </description>
              </parameter>
              <description>
                <para>
                  Construct an expression node with tag type <computeroutput>Tag</computeroutput> and in the
                  domain <computeroutput>Domain</computeroutput>.
                </para>
              </description>
              <returns>
                <para>
                  <computeroutput><functionname>proto::unpack_expr</functionname>&lt;Tag, Domain&gt;(sequence)</computeroutput>
                </para>
              </returns>
            </method>
          </method-group>
        </struct>
      </namespace>
      
      <namespace name="result_of">
        <!-- proto::result_of::make_expr -->
        <struct name="make_expr">
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="A" pack="1"/>
          </template>
          <purpose>Metafunction that computes the return type of the
            <computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput>
            function, with a domain deduced from the domains of the children.</purpose>
          <description>
            <para>
              Computes the return type of the
              <computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput> function.
            </para>
            <para>
              In this specialization, the domain is deduced from the domains of the child types.
              If <computeroutput><classname>proto::is_domain</classname>&lt;A<subscript>0</subscript>&gt;::value</computeroutput>
              is <computeroutput>true</computeroutput>, then another specialization is selected.
            </para>
          </description>
          <typedef name="D">
            <purpose>For exposition only</purpose>
            <type><replaceable>domain-deduced-from-child-types</replaceable></type>
            <description>
              <para>
                For each <computeroutput>x</computeroutput> in <computeroutput>[0,N)</computeroutput>
                (proceeding in order beginning with <computeroutput>x=0</computeroutput>), if
                <computeroutput><classname>proto::domain_of</classname>&lt;A<subscript>x</subscript>&gt;::type</computeroutput> is not
                <computeroutput><classname>proto::default_domain</classname></computeroutput>, then
                <computeroutput>D</computeroutput> is
                <computeroutput><classname>proto::domain_of</classname>&lt;A<subscript>x</subscript>&gt;::type</computeroutput>. 
                Otherwise, <computeroutput>D</computeroutput> is
                <computeroutput><classname>proto::default_domain</classname></computeroutput>.
              </para>
            </description>
          </typedef>
          <typedef name="type">
            <type>typename <classname>proto::result_of::make_expr</classname>&lt;Tag, D, A...&gt;::type</type>
          </typedef>
        </struct>
        <struct-specialization name="make_expr">
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Domain"/>
            <template-type-parameter name="A" pack="1"/>
          </template>
          <specialization>
            <template-arg>Tag</template-arg>
            <template-arg>Domain</template-arg>
            <template-arg pack="1">A</template-arg>
          </specialization>
          <purpose>Metafunction that computes the return type of the
            <computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput>
            function, within the specified domain.</purpose>
          <description>
            <para>
              Computes the return type of the
              <computeroutput><functionname alt="proto::make_expr">proto::make_expr()</functionname></computeroutput>
              function.
            </para>
          </description>
          <typedef name="type">
            <description>
              <para>
                If <computeroutput>Tag</computeroutput> is
                <computeroutput><classname>proto::tag::terminal</classname></computeroutput>, then
                <computeroutput>type</computeroutput> is a typedef for
                <computeroutput>boost::result_of&lt;Domain(<classname>proto::expr</classname>&lt;
                <classname>proto::tag::terminal</classname>, <classname>proto::term</classname>&lt;
                A<subscript>0</subscript> &gt; &gt;)&gt;::type</computeroutput>.
              </para>
              <para>
                Otherwise, <computeroutput>type</computeroutput> is a typedef for
                <computeroutput>boost::result_of&lt;Domain(<classname>proto::expr</classname>&lt;
                Tag, <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname>&lt;
                typename <classname>proto::result_of::as_child</classname>&lt;A&gt;::type...&gt; &gt;)&gt;::type</computeroutput>
              </para>
            </description>
            <type><emphasis>see-below</emphasis></type>
          </typedef>
        </struct-specialization>
        <!-- proto::result_of::unpack_expr -->
        <struct name="unpack_expr">
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Sequence"/>
            <template-type-parameter name="Void">
              <default><type>void</type></default>
            </template-type-parameter>
          </template>
          <purpose>Metafunction that computes the return type of the
            <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
            function, with a domain deduced from the domains of the children.
          </purpose>
          <description>
            <para>
              Compute the return type of the
              <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
              function.
            </para>
            <para>
              <computeroutput>Sequence</computeroutput> is a Fusion Random Access Sequence.
            </para>
            <para>
              In this specialization, the domain is deduced from the domains of the child types.
              If <computeroutput><classname>proto::is_domain</classname>&lt;Sequence&gt;::value</computeroutput>
              is <computeroutput>true</computeroutput>, then another specialization is selected.
            </para>
          </description>
          <typedef name="type">
            <purpose>Where N is the size of Sequence.</purpose>
            <type>
    typename <classname>proto::result_of::make_expr</classname>&lt;
      Tag,
      typename fusion::value_at&lt;Sequence, 0&gt;::type,
      ...
      typename fusion::value_at&lt;Sequence, <replaceable>N</replaceable>-1&gt;::type
    &gt;::type
  </type>
          </typedef>
        </struct>
        <struct-specialization name="unpack_expr">
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Domain"/>
            <template-type-parameter name="Sequence"/>
          </template>
          <specialization>
            <template-arg>Tag</template-arg>
            <template-arg>Domain</template-arg>
            <template-arg>Sequence</template-arg>
          </specialization>
          <purpose>Metafunction that computes the return type of the
            <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
            function, within the specified domain.
          </purpose>
          <description>
            <para>
              Computes the return type of the
              <computeroutput><functionname alt="proto::unpack_expr">proto::unpack_expr()</functionname></computeroutput>
              function.
            </para>
          </description>
          <typedef name="type">
            <purpose>Where N is the size of Sequence.</purpose>
            <type>
    typename <classname>proto::result_of::make_expr</classname>&lt;
      Tag,
      Domain,
      typename fusion::value_at&lt;Sequence, 0&gt;::type,
      ...
      typename fusion::value_at&lt;Sequence, <replaceable>N</replaceable>-1&gt;::type
    &gt;::type
  </type>
          </typedef>
        </struct-specialization>
      </namespace>

      <!-- proto::make_expr() -->
      <overloaded-function name="make_expr">
        <signature>
          <type>typename <classname>proto::result_of::make_expr</classname>&lt;Tag, A const...&gt;::type const</type>
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="A" pack="1"/>
          </template>
          <parameter name="a" pack="1">
            <paramtype>A const &amp;</paramtype>
          </parameter>
        </signature>
        <signature>
          <type>typename <classname>proto::result_of::make_expr</classname>&lt;Tag, Domain, A const...&gt;::type const</type>
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Domain"/>
            <template-type-parameter name="A" pack="1"/>
          </template>
          <parameter name="a" pack="1">
            <paramtype>A const &amp;</paramtype>
          </parameter>
        </signature>
        <purpose>Construct an expression of the requested tag type with a domain and with the specified
          arguments as children.</purpose>
        <description>
          <para>
            This function template may be invoked either with or without specifying a
            <computeroutput>Domain</computeroutput> template parameter. If no domain is specified, the domain
            is deduced by examining in order the domains of the given arguments and taking the first that is
            not <computeroutput><classname>proto::default_domain</classname></computeroutput>, if any such
            domain exists, or <computeroutput><classname>proto::default_domain</classname></computeroutput>
            otherwise.
          </para>
          <para>
            Let <computeroutput><replaceable>WRAP</replaceable>(x)</computeroutput> be defined such that:
            <itemizedlist>
              <listitem>
                <para>
                  If <computeroutput>x</computeroutput> is a <computeroutput>boost::reference_wrapper&lt;&gt;</computeroutput>,
                  <computeroutput><replaceable>WRAP</replaceable>(x)</computeroutput> is equivalent to
                  <computeroutput><functionname>proto::as_child</functionname>&lt;Domain&gt;(x.get())</computeroutput>.
                </para>
              </listitem>
              <listitem>
                <para>
                  Otherwise, <computeroutput><replaceable>WRAP</replaceable>(x)</computeroutput> is equivalent to
                  <computeroutput><functionname>proto::as_expr</functionname>&lt;Domain&gt;(x)</computeroutput>.
                </para>
              </listitem>
            </itemizedlist>
            Let <computeroutput><replaceable>MAKE</replaceable>&lt;Tag&gt;(a...)</computeroutput> be defined as
            <computeroutput><classname>proto::expr</classname>&lt;Tag,
            <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname>&lt;A...&gt; &gt;::make(a...)</computeroutput>
            where
            <computeroutput>A<subscript>x</subscript></computeroutput> is the type of 
            <computeroutput>a<subscript>x</subscript></computeroutput>.
          </para>
          <para>
          </para>
        </description>
        <returns>
          <para>
            <computeroutput>Domain()(<replaceable>MAKE</replaceable>&lt;Tag&gt;(<replaceable>WRAP</replaceable>(a)...))</computeroutput>.
          </para>
        </returns>
      </overloaded-function>

      <!-- proto::unpack_expr() -->
      <overloaded-function name="unpack_expr">
        <signature>
          <type>typename <classname>proto::result_of::unpack_expr</classname>&lt;Tag, Sequence const&gt;::type const</type>
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Sequence"/>
          </template>
          <parameter name="sequence">
            <paramtype>Sequence const &amp;</paramtype>
            <description>
              <para>A Fusion Random Access Sequence.</para>
            </description>
          </parameter>
        </signature>
        <signature>
          <type>typename <classname>proto::result_of::unpack_expr</classname>&lt;Tag, Domain, Sequence const&gt;::type const</type>
          <template>
            <template-type-parameter name="Tag"/>
            <template-type-parameter name="Domain"/>
            <template-type-parameter name="Sequence"/>
          </template>
          <parameter name="sequence">
            <paramtype>Sequence const &amp;</paramtype>
          </parameter>
        </signature>
        <purpose>Construct an expression of the requested tag type with a domain and with children
          from the specified Fusion Random Access Sequence.</purpose>
        <description>
          <para>
            This function template may be invoked either with or without specifying a
            <computeroutput>Domain</computeroutput> argument. If no domain is specified, the domain is
            deduced by examining in order the domains of the elements of <computeroutput>sequence</computeroutput>
            and taking the first that is not
            <computeroutput><classname>proto::default_domain</classname></computeroutput>, if any such domain
            exists, or <computeroutput><classname>proto::default_domain</classname></computeroutput> otherwise.
          </para>
          <para>
            Let <computeroutput><replaceable>WRAP</replaceable>&lt;N&gt;(s)</computeroutput>, where
            <computeroutput>s</computeroutput> has type <computeroutput>S</computeroutput>, be defined such that:
            <itemizedlist>
              <listitem>
                <para>
                  If <computeroutput>fusion::value_at&lt;S,N&gt;::type</computeroutput> is a reference,
                  <computeroutput><replaceable>WRAP</replaceable>&lt;N&gt;(s)</computeroutput> is equivalent to
                  <computeroutput><functionname>proto::as_child</functionname>&lt;Domain&gt;(fusion::at_c&lt;N&gt;(s))</computeroutput>.
                </para>
              </listitem>
              <listitem>
                <para>
                  Otherwise, <computeroutput><replaceable>WRAP</replaceable>&lt;N&gt;(s)</computeroutput> is equivalent to
                  <computeroutput><functionname>proto::as_expr</functionname>&lt;Domain&gt;(fusion::at_c&lt;N&gt;(s))</computeroutput>.
                </para>
              </listitem>
            </itemizedlist>
            Let <computeroutput><replaceable>MAKE</replaceable>&lt;Tag&gt;(a...)</computeroutput> be defined as
            <computeroutput><classname>proto::expr</classname>&lt;Tag,
            <classname alt="proto::listN">proto::list<emphasis>N</emphasis></classname>&lt;A...&gt; &gt;::make(a...)</computeroutput>
            where
            <computeroutput>A<subscript>x</subscript></computeroutput> is the type of 
            <computeroutput>a<subscript>x</subscript></computeroutput>.
          </para>
        </description>
        <returns>
          <para>
            <computeroutput>Domain()(<replaceable>MAKE</replaceable>&lt;Tag&gt;(<replaceable>WRAP</replaceable>&lt;0&gt;(s),...
            <replaceable>WRAP</replaceable>&lt;<replaceable>N</replaceable>-1&gt;(s)))</computeroutput>, where
            <replaceable>N</replaceable> is the size of <computeroutput>Sequence</computeroutput>.
          </para>
        </returns>
      </overloaded-function>
    </namespace>
  </namespace>
</header>
