123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- <?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/extends.hpp">
- <para>Macros and a base class for defining end-user expression types </para>
- <namespace name="boost">
- <namespace name="proto">
- <!-- proto::is_proto_expr -->
- <struct name="is_proto_expr">
- <purpose>Empty type to be used as a dummy template parameter of POD expression wrappers. It allows
- argument-dependent lookup to find Proto's operator overloads.</purpose>
- <description>
- <para>
- <computeroutput>proto::is_proto_expr</computeroutput> allows argument-dependent lookup to find Proto's operator overloads. For example:
- </para>
- <para>
- <programlisting> template<typename T, typename Dummy = <classname>proto::is_proto_expr</classname>>
- struct my_terminal
- {
- <macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>(
- typename <classname>proto::terminal</classname><T>::type
- , my_terminal<T>
- , <classname>proto::default_domain</classname>
- )
- };
- // ...
- my_terminal<int> _1, _2;
- _1 + _2; // OK, uses proto::operator+</programlisting>
- </para>
- <para>
- Without the second <computeroutput>Dummy</computeroutput> template parameter, Proto's operator overloads
- would not be considered by name lookup.
- </para>
- </description>
- </struct>
- <!-- proto::extends -->
- <struct name="extends">
- <template>
- <template-type-parameter name="Expr"/>
- <template-type-parameter name="Derived"/>
- <template-type-parameter name="Domain">
- <default><classname>proto::default_domain</classname></default>
- </template-type-parameter>
- </template>
- <purpose>For adding behaviors to a Proto expression template.</purpose>
- <description>
- <para>
- Use <computeroutput>proto::extends<></computeroutput> to give expressions in your
- domain custom data members and member functions.
- </para>
- <para>
- Conceptually, using <computeroutput>proto::extends<></computeroutput> is akin
- to inheriting from <computeroutput><classname>proto::expr</classname><></computeroutput>
- and adding your own members. Using <computeroutput>proto::extends<></computeroutput> is
- generally preferrable to straight inheritance because the members that would be inherited from
- <computeroutput><classname>proto::expr</classname><></computeroutput> would
- be wrong; they would incorrectly slice off your additional members when building
- larger expressions from smaller ones. <computeroutput>proto::extends<></computeroutput>
- automatically gives your expression types the appropriate operator overloads that
- preserve your domain-specific members when composing expression trees.
- </para>
- <para>
- Expression extensions are typically defined as follows:
- </para>
- <para>
- <programlisting>template< typename Expr >
- struct my_expr
- : proto::extends<
- Expr // The expression type we're extending
- , my_expr< Expr > // The type we're defining
- , my_domain // The domain associated with this expression extension
- >
- {
- // An expression extension is constructed from the expression
- // it is extending.
- my_expr( Expr const & e = Expr() )
- : my_expr::proto_extends( e )
- {}
-
- // Unhide proto::extends::operator=
- // (This is only necessary if a lazy assignment operator
- // makes sense for your domain-specific language.)
- BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expr)
-
- /*
- ... domain-specific members go here ...
- */
- };</programlisting>
- </para>
- <para>
- See also:
- <itemizedlist>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT</macroname>()</computeroutput>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- <struct name="result">
- <template>
- <template-type-parameter name="Signature"/>
- </template>
- <typedef name="type">
- <type><replaceable>unspecified</replaceable></type>
- </typedef>
- <description>
- <para>So that <computeroutput>boost::result_of<></computeroutput>
- can compute the return type of <computeroutput>proto::extends::operator()</computeroutput>.
- </para>
- </description>
- </struct>
- <typedef name="proto_base_expr">
- <type>typename Expr::proto_base_expr</type>
- </typedef>
- <typedef name="proto_domain">
- <type>Domain</type>
- </typedef>
- <typedef name="proto_derived_expr">
- <type>Derived</type>
- </typedef>
- <typedef name="proto_extends">
- <type>extends</type>
- </typedef>
- <typedef name="proto_tag">
- <type>typename proto_base_expr::proto_tag</type>
- </typedef>
- <typedef name="proto_args">
- <type>typename proto_base_expr::proto_args</type>
- </typedef>
- <typedef name="proto_arity">
- <type>typename proto_base_expr::proto_arity</type>
- </typedef>
- <typedef name="proto_grammar">
- <type>typename proto_base_expr::proto_grammar</type>
- </typedef>
- <typedef name="proto_childN">
- <purpose>For each <replaceable>N</replaceable> in <replaceable>[0,max(1,proto_arity_c))</replaceable></purpose>
- <type>typename proto_base_expr::proto_child<replaceable>N</replaceable></type>
- </typedef>
- <!-- constructors -->
- <constructor/>
- <constructor>
- <parameter name="that">
- <paramtype><classname>extends</classname> const &</paramtype>
- </parameter>
- </constructor>
- <constructor>
- <parameter name="expr_">
- <paramtype>Expr const &</paramtype>
- </parameter>
- </constructor>
- <method-group name="public static functions">
- <method name="make" specifiers="static">
- <type>Derived const</type>
- <parameter name="expr">
- <paramtype>Expr const &</paramtype>
- </parameter>
- <description>
- <para>Construct an expression extension from the base expression.</para>
- </description>
- <return>Derived(expr)</return>
- </method>
- </method-group>
- <method-group name="public member functions">
- <!-- proto_base() -->
- <method name="proto_base">
- <type>proto_base_expr &</type>
- <returns><computeroutput>proto_expr_.proto_base()</computeroutput></returns>
- <throws><simpara>Will not throw.</simpara></throws>
- </method>
- <method name="proto_base" cv="const">
- <type>proto_base_expr const &</type>
- <returns><computeroutput>proto_expr_.proto_base()</computeroutput></returns>
- <throws><simpara>Will not throw.</simpara></throws>
- </method>
- <!-- operator= -->
- <method name="operator=">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A &</paramtype>
- </parameter>
- <description>
- <para>Lazy assignment expression</para>
- </description>
- <returns>
- <para>A new expression node representing the assignment operation.</para>
- </returns>
- </method>
- <method name="operator=">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A const &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- <method name="operator=" cv="const">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- <method name="operator=" cv="const">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A const &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- <!-- operator[] -->
- <method name="operator[]">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A &</paramtype>
- </parameter>
- <description>
- <para>Lazy subscript expression</para>
- </description>
- <returns>
- <para>A new expression node representing the subscript operation.</para>
- </returns>
- </method>
- <method name="operator[]">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A const &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- <method name="operator[]" cv="const">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- <method name="operator[]" cv="const">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A"/>
- </template>
- <parameter name="a">
- <paramtype>A const &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- <!-- operator() -->
- <method name="operator()">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A" pack="1"/>
- </template>
- <parameter name="a" pack="1">
- <paramtype>A const &</paramtype>
- </parameter>
- <description>
- <para>Lazy function call</para>
- </description>
- <returns>
- <para>A new expression node representing the function call operation.</para>
- </returns>
- </method>
- <method name="operator()" cv="const">
- <type><replaceable>unspecified</replaceable></type>
- <template>
- <template-type-parameter name="A" pack="1"/>
- </template>
- <parameter name="a" pack="1">
- <paramtype>A const &</paramtype>
- </parameter>
- <description>
- <para>
- This is an overloaded member function, provided for convenience. It differs from
- the above function only in what argument(s) it accepts.
- </para>
- </description>
- </method>
- </method-group>
- <data-member name="proto_expr_">
- <type>Expr</type>
- <purpose>For exposition only.</purpose>
- </data-member>
- <data-member name="proto_arity_c" specifiers="static">
- <type>const long</type>
- <purpose><computeroutput>= proto_base_expr::proto_arity_c;</computeroutput></purpose>
- </data-member>
- </struct>
- </namespace>
- </namespace>
- <macro name="BOOST_PROTO_EXTENDS" kind="functionlike">
- <macro-parameter name="Expr"/>
- <macro-parameter name="Derived"/>
- <macro-parameter name="Domain"/>
- <purpose>For creating expression wrappers that add behaviors to a Proto expression template, like
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>,
- but while retaining POD-ness of the expression wrapper.</purpose>
- <description>
- <para>
- Equivalent to:
- <programlisting><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>(Expr, Derived, Domain)
- <macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()
- <macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()
- <macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</programlisting>
- </para>
- <para>If the <computeroutput>Domain</computeroutput> parameter is dependent, you can specify it as
- <computeroutput>typename Domain</computeroutput>, as in
- <computeroutput>BOOST_PROTO_EXTENDS(Expr, Derived, typename Domain)</computeroutput>
- </para>
- <para>
- <emphasis role="bold">Example:</emphasis><programlisting>template< class Expr >
- struct my_expr;
- struct my_domain
- : <classname alt="boost::proto::domain">proto::domain</classname>< <classname alt="boost::proto::pod_generator">proto::pod_generator</classname>< my_expr > >
- {};
- template< class Expr >
- struct my_expr
- {
- // OK, this makes my_expr<> a valid Proto expression extension.
- // my_expr<> has overloaded assignment, subscript,
- // and function call operators that build expression templates.
- <macroname>BOOST_PROTO_EXTENDS</macroname>(Expr, my_expr, my_domain)
- };
- // OK, my_expr<> is POD, so this is statically initialized:
- my_expr< <classname alt="boost::proto::terminal">proto::terminal</classname><int>::type > const _1 = {{1}};</programlisting>
- </para>
- </description>
- </macro>
- <macro name="BOOST_PROTO_BASIC_EXTENDS" kind="functionlike">
- <macro-parameter name="Expr"/>
- <macro-parameter name="Derived"/>
- <macro-parameter name="Domain"/>
- <purpose>For creating expression wrappers that add members to a Proto expression template, like
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>,
- but while retaining POD-ness of the expression wrapper.</purpose>
- <description>
- <para>
- <computeroutput>BOOST_PROTO_BASIC_EXTENDS()</computeroutput> adds the basic typedefs, member functions, and
- data members necessary to make a struct a valid Proto expression extension. It does <emphasis>not</emphasis>
- add any constructors, virtual functions or access control blocks that would render the containing
- struct non-POD.
- </para>
- <para>
- <computeroutput>Expr</computeroutput> is the Proto expression that the enclosing struct extends.
- <computeroutput>Derived</computeroutput> is the type of the enclosing struct.
- <computeroutput>Domain</computeroutput> is the Proto domain to which this expression extension belongs.
- (See <computeroutput><classname alt="boost::proto::domain">proto::domain<></classname></computeroutput>.)
- Can be preceeded with "<computeroutput>typename</computeroutput>" if the specified domain is a dependent type.
- </para>
- <para><computeroutput>BOOST_PROTO_BASIC_EXTENDS()</computeroutput> adds to its enclosing struct
- exactly one data member of type <computeroutput>Expr</computeroutput>.
- </para>
- <para>If the <computeroutput>Domain</computeroutput> parameter is dependent, you can specify it as
- <computeroutput>typename Domain</computeroutput>, as in
- <computeroutput>BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, typename Domain)</computeroutput>
- </para>
- <para>
- <emphasis role="bold">Example:</emphasis><programlisting>template< class Expr >
- struct my_expr;
- struct my_domain
- : <classname alt="boost::proto::domain">proto::domain</classname>< <classname alt="boost::proto::pod_generator">proto::pod_generator</classname>< my_expr > >
- {};
- template< class Expr >
- struct my_expr
- {
- // OK, this makes my_expr<> a valid Proto expression extension.
- // my_expr<> does /not/ have overloaded assignment, subscript,
- // and function call operators that build expression templates, however.
- <macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>(Expr, my_expr, my_domain)
- };
- // OK, my_expr<> is POD, so this is statically initialized:
- my_expr< <classname alt="boost::proto::terminal">proto::terminal</classname><int>::type > const _1 = {{1}};</programlisting>
- </para>
- <para>
- See also:
- <itemizedlist>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- </macro>
- <macro name="BOOST_PROTO_EXTENDS_ASSIGN" kind="functionlike">
- <purpose>For adding to an expression extension class an overloaded assignment operator that
- builds an expression template.</purpose>
- <description>
- <para>
- Use <computeroutput>BOOST_PROTO_EXTENDS_ASSIGN()</computeroutput> after <computeroutput>
- <macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput> to give an expression
- extension class an overloaded assignment operator that builds an expression template.
- </para>
- <para>
- See also:
- <itemizedlist>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- </macro>
- <macro name="BOOST_PROTO_EXTENDS_FUNCTION" kind="functionlike">
- <purpose>For adding to an expression extension class a set of overloaded function call operators
- that build expression templates.</purpose>
- <description>
- <para>
- Use <computeroutput>BOOST_PROTO_EXTENDS_FUNCTION()</computeroutput> after <computeroutput>
- <macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput> to give an expression
- extension class a set of overloaded function call operators that build expression templates.
- In addition, <computeroutput>BOOST_PROTO_EXTENDS_FUNCTION()</computeroutput> adds a nested
- <computeroutput>result<></computeroutput> class template that is a metafunction for
- calculating the return type of the overloaded function call operators.
- </para>
- <para>
- See also:
- <itemizedlist>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_SUBSCRIPT</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- </macro>
- <macro name="BOOST_PROTO_EXTENDS_SUBSCRIPT" kind="functionlike">
- <purpose>For adding to an expression extension class an overloaded subscript operator that
- builds an expression template.</purpose>
- <description>
- <para>
- Use <computeroutput>BOOST_PROTO_EXTENDS_SUBSCRIPT()</computeroutput> after <computeroutput>
- <macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput> to give an expression
- extension class an overloaded subscript operator that builds an expression template.
- </para>
- <para>
- See also:
- <itemizedlist>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_BASIC_EXTENDS</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_ASSIGN</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_FUNCTION</macroname>()</computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS</macroname>()</computeroutput>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- </macro>
- <macro name="BOOST_PROTO_EXTENDS_USING_ASSIGN" kind="functionlike">
- <macro-parameter name="Derived"/>
- <purpose>For exposing in classes that inherit from
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>
- the overloaded assignment operators defined therein.</purpose>
- <description>
- <para>
- The standard usage of
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>
- is to inherit from it. However, the derived class automatically gets a compiler-generated assignment
- operator that will hide the ones defined in
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>.
- Use <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code> in the derived class to unhide the assignment
- operators defined in
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>.
- </para>
- <para>
- See <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>
- for an example that demonstrates usage of <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code>.
- </para>
- </description>
- </macro>
- <macro name="BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT" kind="functionlike">
- <macro-parameter name="Derived"/>
- <purpose>For exposing in classes that inherit from
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>
- the overloaded assignment operators defined therein. Unlike the
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN</macroname>()</computeroutput> macro,
- <code>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT()</code> is for use in non-dependent
- contexts.
- </purpose>
- <description>
- <para>
- The standard usage of
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>
- is to define a class template that inherits from it. The derived class template automatically gets a
- compiler-generated assignment operator that hides the ones defined in
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>.
- Using <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code> in the derived class solves this problem.
- </para>
- <para>
- However, if the expression extension is an ordinary class and not a class template, the usage of
- <code>BOOST_PROTO_EXTENDS_USING_ASSIGN()</code> is in a so-called non-dependent context. In plain English,
- it means it is illegal to use <code>typename</code> in some places where it is required in a class template.
- In those cases, you should use <code>BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT()</code> instead.
- </para>
- <para>
- See also:
- <itemizedlist>
- <listitem>
- <computeroutput><classname alt="boost::proto::extends">proto::extends<></classname></computeroutput>
- </listitem>
- <listitem>
- <computeroutput><macroname>BOOST_PROTO_EXTENDS_USING_ASSIGN</macroname>()</computeroutput>
- </listitem>
- </itemizedlist>
- </para>
- </description>
- </macro>
- </header>
|