2010-04-28 16:09:03 +00:00
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=US-ASCII" >
< title > Introduction and motivation< / title >
< link rel = "stylesheet" href = "../../../../../../../doc/html/boostbook.css" type = "text/css" >
< meta name = "generator" content = "DocBook XSL Stylesheets V1.75.1" >
< link rel = "home" href = "../../../index.html" title = "Chapter 1. Range 2.0" >
< link rel = "up" href = "../adaptors.html" title = "Range Adaptors" >
< link rel = "prev" href = "../adaptors.html" title = "Range Adaptors" >
2010-04-28 18:03:26 +00:00
< link rel = "next" href = "general_requirements.html" title = "General Requirements" >
2010-04-28 16:09:03 +00:00
< / head >
< body bgcolor = "white" text = "black" link = "#0000FF" vlink = "#840084" alink = "#0000FF" >
< table cellpadding = "2" width = "100%" > < tr >
< td valign = "top" > < img alt = "Boost C++ Libraries" width = "277" height = "86" src = "../../../../../../../boost.png" > < / td >
< td align = "center" > < a href = "../../../../../../../index.html" > Home< / a > < / td >
< td align = "center" > < a href = "../../../../../../libraries.htm" > Libraries< / a > < / td >
< td align = "center" > < a href = "http://www.boost.org/users/people.html" > People< / a > < / td >
< td align = "center" > < a href = "http://www.boost.org/users/faq.html" > FAQ< / a > < / td >
< td align = "center" > < a href = "../../../../../../../more/index.htm" > More< / a > < / td >
< / tr > < / table >
< hr >
< div class = "spirit-nav" >
2010-04-28 18:03:26 +00:00
< a accesskey = "p" href = "../adaptors.html" > < img src = "../../../../../../../doc/html/images/prev.png" alt = "Prev" > < / a > < a accesskey = "u" href = "../adaptors.html" > < img src = "../../../../../../../doc/html/images/up.png" alt = "Up" > < / a > < a accesskey = "h" href = "../../../index.html" > < img src = "../../../../../../../doc/html/images/home.png" alt = "Home" > < / a > < a accesskey = "n" href = "general_requirements.html" > < img src = "../../../../../../../doc/html/images/next.png" alt = "Next" > < / a >
2010-04-28 16:09:03 +00:00
< / div >
< div class = "section" title = "Introduction and motivation" >
< div class = "titlepage" > < div > < div > < h4 class = "title" >
< a name = "range.reference.adaptors.introduction" > < / a > < a class = "link" href = "introduction.html" title = "Introduction and motivation" > Introduction
and motivation< / a >
< / h4 > < / div > < / div > < / div >
< p >
A < span class = "bold" > < strong > Range Adaptor< / strong > < / span > is a class that wraps
an existing Range to provide a new Range with different behaviour. Since
the behaviour of Ranges is determined by their associated iterators, a
Range Adaptor simply wraps the underlying iterators with new special iterators.
In this example
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "preprocessor" > #include< / span > < span class = "special" > < < / span > < span class = "identifier" > boost< / span > < span class = "special" > /< / span > < span class = "identifier" > range< / span > < span class = "special" > /< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > .< / span > < span class = "identifier" > hpp< / span > < span class = "special" > > < / span >
< span class = "preprocessor" > #include< / span > < span class = "special" > < < / span > < span class = "identifier" > boost< / span > < span class = "special" > /< / span > < span class = "identifier" > range< / span > < span class = "special" > /< / span > < span class = "identifier" > algorithm< / span > < span class = "special" > .< / span > < span class = "identifier" > hpp< / span > < span class = "special" > > < / span >
< span class = "preprocessor" > #include< / span > < span class = "special" > < < / span > < span class = "identifier" > iostream< / span > < span class = "special" > > < / span >
< span class = "preprocessor" > #include< / span > < span class = "special" > < < / span > < span class = "identifier" > vector< / span > < span class = "special" > > < / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > vector< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > < / span > < span class = "identifier" > vec< / span > < span class = "special" > ;< / span >
< span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reversed< / span > < span class = "special" > ,< / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > ostream_iterator< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > (< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > cout< / span > < span class = "special" > )< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
the iterators from < code class = "computeroutput" > < span class = "identifier" > vec< / span > < / code >
are wrapped < code class = "computeroutput" > < span class = "identifier" > reverse_iterator< / span > < / code > s.
The type of the underlying Range Adapter is not documented because you
do not need to know it. All that is relevant is that the expression
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > vec< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reversed< / span >
< / pre >
< p >
< / p >
< p >
returns a Range Adaptor where the iterator type is now the iterator type
of the range < code class = "computeroutput" > < span class = "identifier" > vec< / span > < / code > wrapped
in < code class = "computeroutput" > < span class = "identifier" > reverse_iterator< / span > < / code > . The
expression < code class = "computeroutput" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reversed< / span > < / code > is called an < span class = "bold" > < strong > Adaptor
Generator< / strong > < / span > .
< / p >
< p >
There are two ways of constructing a range adaptor. The first is by using
< code class = "computeroutput" > < span class = "keyword" > operator< / span > < span class = "special" > |()< / span > < / code > .
This is my preferred technique, however while discussing range adaptors
with others it became clear that some users of the library strongly prefer
a more familiar function syntax, so equivalent functions of the present
tense form have been added as an alternative syntax. The equivalent to
< code class = "computeroutput" > < span class = "identifier" > rng< / span > < span class = "special" > |< / span >
< span class = "identifier" > reversed< / span > < / code > is < code class = "computeroutput" > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reverse< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > )< / span > < / code > for example.
< / p >
< p >
Why do I prefer the < code class = "computeroutput" > < span class = "keyword" > operator< / span > < span class = "special" > |< / span > < / code > syntax? The answer is readability:
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > vector< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > < / span > < span class = "identifier" > vec< / span > < span class = "special" > ;< / span >
< span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy< / span > < span class = "special" > (< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reverse< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > ),< / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > ostream_iterator< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > (< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > cout< / span > < span class = "special" > )< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
This might not look so bad, but when we apply several adaptors, it becomes
much worse. Just compare
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > vector< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > < / span > < span class = "identifier" > vec< / span > < span class = "special" > ;< / span >
< span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy< / span > < span class = "special" > (< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > unique< / span > < span class = "special" > (< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reverse< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > )< / span > < span class = "special" > ),< / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > ostream_iterator< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > (< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > cout< / span > < span class = "special" > )< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
to
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > vector< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > < / span > < span class = "identifier" > vec< / span > < span class = "special" > ;< / span >
< span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reversed< / span >
< span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > uniqued< / span > < span class = "special" > ,< / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > ostream_iterator< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > (< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > cout< / span > < span class = "special" > )< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
Furthermore, some of the adaptor generators take arguments themselves and
these arguments are expressed with function call notation too. In those
situations, you will really appreciate the succinctness of < code class = "computeroutput" > < span class = "keyword" > operator< / span > < span class = "special" > |()< / span > < / code > .
< / p >
< a name = "range.reference.adaptors.introduction.composition_of_adaptors" > < / a > < h6 >
2010-04-28 19:27:44 +00:00
< a name = "id3065833" > < / a >
2010-04-28 16:09:03 +00:00
< a class = "link" href = "introduction.html#range.reference.adaptors.introduction.composition_of_adaptors" > Composition
of Adaptors< / a >
< / h6 >
< p >
Range Adaptors are a powerful complement to Range algorithms. The reason
is that adaptors are < span class = "emphasis" > < em > < span class = "bold" > < strong > orthogonal< / strong > < / span > < / em > < / span >
to algorithms. For example, consider these Range algorithms:
< / p >
< div class = "itemizedlist" > < ul class = "itemizedlist" type = "disc" >
< li class = "listitem" > < code class = "computeroutput" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > ,< / span > < span class = "identifier" > out< / span > < span class = "special" > )< / span > < / code > < / li >
< li class = "listitem" > < code class = "computeroutput" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > count< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > ,< / span > < span class = "identifier" > pred< / span > < span class = "special" > )< / span > < / code > < / li >
< / ul > < / div >
< p >
What should we do if we only want to copy an element < code class = "computeroutput" > < span class = "identifier" > a< / span > < / code >
if it satisfies some predicate, say < code class = "computeroutput" > < span class = "identifier" > pred< / span > < span class = "special" > (< / span > < span class = "identifier" > a< / span > < span class = "special" > )< / span > < / code > ?
And what if we only want to count the elements that satisfy the same predicate?
The naive answer would be to use these algorithms:
< / p >
< div class = "itemizedlist" > < ul class = "itemizedlist" type = "disc" >
< li class = "listitem" > < code class = "computeroutput" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy_if< / span > < span class = "special" > (< / span >
< span class = "identifier" > rng< / span > < span class = "special" > ,< / span >
< span class = "identifier" > pred< / span > < span class = "special" > ,< / span >
< span class = "identifier" > out< / span > < span class = "special" > )< / span > < / code > < / li >
< li class = "listitem" > < code class = "computeroutput" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > count_if< / span > < span class = "special" > (< / span >
< span class = "identifier" > rng< / span > < span class = "special" > ,< / span >
< span class = "identifier" > pred< / span > < span class = "special" > )< / span > < / code > < / li >
< / ul > < / div >
< p >
These algorithms are only defined to maintain a one to one relationship
with the standard library algorithms. This approach of adding algorithm
suffers a combinatorial explosion. Inevitably many algorithms are missing
< code class = "computeroutput" > < span class = "identifier" > _if< / span > < / code > variants and there
is redundant development overhead for each new algorithm. The Adaptor Generator
is the design solution to this problem.
< / p >
< a name = "range.reference.adaptors.introduction.range_adaptor_alternative_to_copy_if_algorithm" > < / a > < h6 >
2010-04-28 19:27:44 +00:00
< a name = "id3066116" > < / a >
2010-04-28 16:09:03 +00:00
< a class = "link" href = "introduction.html#range.reference.adaptors.introduction.range_adaptor_alternative_to_copy_if_algorithm" > Range
Adaptor alternative to copy_if algorithm< / a >
< / h6 >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy_if< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > ,< / span > < span class = "identifier" > pred< / span > < span class = "special" > ,< / span > < span class = "identifier" > out< / span > < span class = "special" > );< / span >
< / pre >
< p >
can be expressed as
< / p >
< pre class = "programlisting" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > copy< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > filtered< / span > < span class = "special" > (< / span > < span class = "identifier" > pred< / span > < span class = "special" > ),< / span > < span class = "identifier" > out< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< a name = "range.reference.adaptors.introduction.range_adaptor_alternative_to_count_if_algorithm" > < / a > < h6 >
2010-04-28 19:27:44 +00:00
< a name = "id3066285" > < / a >
2010-04-28 16:09:03 +00:00
< a class = "link" href = "introduction.html#range.reference.adaptors.introduction.range_adaptor_alternative_to_count_if_algorithm" > Range
Adaptor alternative to count_if algorithm< / a >
< / h6 >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > count_if< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > ,< / span > < span class = "identifier" > pred< / span > < span class = "special" > );< / span >
< / pre >
< p >
can be expressed as
< / p >
< pre class = "programlisting" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > count< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > filtered< / span > < span class = "special" > (< / span > < span class = "identifier" > pred< / span > < span class = "special" > ),< / span > < span class = "identifier" > out< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
What this means is that < span class = "emphasis" > < em > < span class = "bold" > < strong > no< / strong > < / span > < / em > < / span >
algorithm with the < code class = "computeroutput" > < span class = "identifier" > _if< / span > < / code >
suffix is needed. Furthermore, it turns out that algorithms with the < code class = "computeroutput" > < span class = "identifier" > _copy< / span > < / code > suffix are not needed either. Consider
the somewhat misdesigned < code class = "computeroutput" > < span class = "identifier" > replace_copy_if< / span > < span class = "special" > ()< / span > < / code > which may be used as
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > vector< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > < / span > < span class = "identifier" > vec< / span > < span class = "special" > ;< / span >
< span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > replace_copy_if< / span > < span class = "special" > (< / span > < span class = "identifier" > rng< / span > < span class = "special" > ,< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > back_inserter< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > ),< / span > < span class = "identifier" > pred< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
With adaptors and algorithms we can express this as
< / p >
< p >
< / p >
< pre class = "programlisting" > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > vector< / span > < span class = "special" > < < / span > < span class = "keyword" > int< / span > < span class = "special" > > < / span > < span class = "identifier" > vec< / span > < span class = "special" > ;< / span >
< span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > push_back< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > ,< / span > < span class = "identifier" > rng< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > replaced_if< / span > < span class = "special" > (< / span > < span class = "identifier" > pred< / span > < span class = "special" > ,< / span > < span class = "identifier" > new_value< / span > < span class = "special" > ));< / span >
< / pre >
< p >
< / p >
< p >
The latter code has several benefits:
< / p >
< p >
1. it is more < span class = "emphasis" > < em > < span class = "bold" > < strong > efficient< / strong > < / span > < / em > < / span >
because we avoid extra allocations as might happen with < code class = "computeroutput" > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > back_inserter< / span > < / code >
< / p >
< p >
2. it is < span class = "emphasis" > < em > < span class = "bold" > < strong > flexible< / strong > < / span > < / em > < / span >
as we can subsequently apply even more adaptors, for example:
< / p >
< pre class = "programlisting" > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > push_back< / span > < span class = "special" > (< / span > < span class = "identifier" > vec< / span > < span class = "special" > ,< / span > < span class = "identifier" > rng< / span > < span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > replaced_if< / span > < span class = "special" > (< / span > < span class = "identifier" > pred< / span > < span class = "special" > ,< / span > < span class = "identifier" > new_value< / span > < span class = "special" > )< / span >
< span class = "special" > |< / span > < span class = "identifier" > boost< / span > < span class = "special" > ::< / span > < span class = "identifier" > adaptors< / span > < span class = "special" > ::< / span > < span class = "identifier" > reversed< / span > < span class = "special" > );< / span >
< / pre >
< p >
< / p >
< p >
3. it is < span class = "emphasis" > < em > < span class = "bold" > < strong > safer< / strong > < / span > < / em > < / span > because
there is no use of an unbounded output iterator.
< / p >
< p >
In this manner, the < span class = "emphasis" > < em > < span class = "bold" > < strong > composition< / strong > < / span > < / em > < / span >
of Range Adaptors has the following consequences:
< / p >
< p >
1. we no longer need < code class = "computeroutput" > < span class = "identifier" > _if< / span > < / code > ,
< code class = "computeroutput" > < span class = "identifier" > _copy< / span > < / code > , < code class = "computeroutput" > < span class = "identifier" > _copy_if< / span > < / code >
and < code class = "computeroutput" > < span class = "identifier" > _n< / span > < / code > variants of algorithms.
< / p >
< p >
2. we can generate a multitude of new algorithms on the fly, for example,
above we generated < code class = "computeroutput" > < span class = "identifier" > reverse_replace_copy_if< / span > < span class = "special" > ()< / span > < / code >
< / p >
< p >
In other words:
< / p >
< p >
< span class = "bold" > < strong > Range Adaptors are to algorithms what algorithms
are to containers< / strong > < / span >
< / p >
< / div >
< table xmlns:rev = "http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width = "100%" > < tr >
< td align = "left" > < / td >
< td align = "right" > < div class = "copyright-footer" > Copyright © 2003 -2010 Thorsten Ottosen, Neil Groves< p >
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at < a href = "http://www.boost.org/LICENSE_1_0.txt" target = "_top" > http://www.boost.org/LICENSE_1_0.txt< / a > )
< / p >
< / div > < / td >
< / tr > < / table >
< hr >
< div class = "spirit-nav" >
2010-04-28 18:03:26 +00:00
< a accesskey = "p" href = "../adaptors.html" > < img src = "../../../../../../../doc/html/images/prev.png" alt = "Prev" > < / a > < a accesskey = "u" href = "../adaptors.html" > < img src = "../../../../../../../doc/html/images/up.png" alt = "Up" > < / a > < a accesskey = "h" href = "../../../index.html" > < img src = "../../../../../../../doc/html/images/home.png" alt = "Home" > < / a > < a accesskey = "n" href = "general_requirements.html" > < img src = "../../../../../../../doc/html/images/next.png" alt = "Next" > < / a >
2010-04-28 16:09:03 +00:00
< / div >
< / body >
< / html >