Topic: Possibility of a : std::invoke() function
Author: jgottman6@gmail.com
Date: Tue, 16 Jul 2013 18:50:25 -0700 (PDT)
Raw View
------=_Part_325_26173525.1374025825230
Content-Type: text/plain; charset=ISO-8859-1
The C++11 standard defines the pseudo-function INVOKE in section 20.8.2.
With the technology available in C++14, would it be possible to define an
actual std::invoke() template function that does the same thing? If so, I
think this would be a good idea,
Also, if we can define a std::invoke function, I would also like a
tuple_invoke function that takes a callable object f and a tuple t and
calls invoke on f and the elements of t. If we can define std::invoke it
would be easy enough to define this function using std::index_sequence.
Joe Gottman
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_325_26173525.1374025825230
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
The C++11 standard defines the pseudo-function INVOKE in section 20.8.2.&nb=
sp; With the technology available in C++14, would it be possible to define =
an actual std::invoke() template function that does the same thing? I=
f so, I think this would be a good idea,<br><br>Also, if we can define a st=
d::invoke function, I would also like a tuple_invoke function that takes a =
callable object f and a tuple t and calls invoke on f and the elements of t=
.. If we can define std::invoke it would be easy enough to define this funct=
ion using std::index_sequence.<br><br><br>Joe Gottman<br><br><br><br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_325_26173525.1374025825230--
.
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@gmail.com>
Date: Thu, 18 Jul 2013 11:32:53 +0200
Raw View
2013/7/17 <jgottman6@gmail.com>:
> The C++11 standard defines the pseudo-function INVOKE in section 20.8.2.
> With the technology available in C++14, would it be possible to define an
> actual std::invoke() template function that does the same thing?
Yes (I have implemented it a while ago and I believe it was already
possible with C++11).
> If so, I think this would be a good idea,
I'm very much in favour to standardize a std::invoke template that
corresponds to the current conceptual INVOKE.
- Daniel
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: tomaszkam@gmail.com
Date: Thu, 18 Jul 2013 04:24:19 -0700 (PDT)
Raw View
------=_Part_1067_27586189.1374146659638
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
W dniu =B6roda, 17 lipca 2013 03:50:25 UTC+2 u=BFytkownik jgot...@gmail.com=
=20
napisa=B3:
>
> The C++11 standard defines the pseudo-function INVOKE in section 20.8.2. =
=20
> With the technology available in C++14, would it be possible to define an=
=20
> actual std::invoke() template function that does the same thing? If so, =
I=20
> think this would be a good idea,
>
> The simplest implementation in C++11 would be:
template<typename Functor, typename Args...>
auto invoke(Functor&& f, Args&&... args)
-> typename std::enable_if<
std::is_member_pointer<typename std::decay<Functor>::type>::value,
decltype(std::mem_fn(f)(std::forward<Args>(args)...))
>::type=20
{ return std::mem_fn(f)(std::forward<Args>(args)...); }
=20
template<typename Functor, typename Args...>
auto invoke(Functor&& f, Args&&... args)
-> typename std::enable_if<
!std::is_member_pointer<typename std::decay<Functor>::type>::value,
decltype(std::forward<Functor>(f)(std::forward<Args>(args)...))
>::type=20
{ return std::forward<Functor>(f)(std::forward<Args>(args)...); }
Of course it can be implemented without using std::mem_fn, if you need so I=
=20
can provide you such implementation.
Also, if we can define a std::invoke function, I would also like a=20
> tuple_invoke function that takes a callable object f and a tuple t and=20
> calls invoke on f and the elements of t. If we can define std::invoke it=
=20
> would be easy enough to define this function using std::index_sequence.
>
> This is only partial solution to the problem, it is allowing only to=20
elements of one tuple as a parameters to function f (you should look for=20
boost::make_fused/unfused). Using the library only based solution solution=
=20
you can implement the expand wrapper, that will allow you to expanded tuple=
=20
with normal functions arguments ex. invoke(f, expand(t1), 10, exapand(t2))=
=20
(implementation of this feature can be found here<https://github.com/tomasz=
kam/tlib>),=20
but this doesnot address problems in case of initialization context=20
(calling constructors, initializers list). The operator...<https://groups.g=
oogle.com/a/isocpp.org/forum/?fromgroups#%21topic/std-proposals/g1HziHt1lbo=
>proposed by me address all of the case of the problems.=20
So I would recommend you to split the work on 2 papers - one that adds=20
std::invoke only and one for std::tuple_invoke.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1067_27586189.1374146659638
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
<br><br>W dniu =B6roda, 17 lipca 2013 03:50:25 UTC+2 u=BFytkownik jgot...@g=
mail.com napisa=B3:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">The C++11 s=
tandard defines the pseudo-function INVOKE in section 20.8.2. With th=
e technology available in C++14, would it be possible to define an actual s=
td::invoke() template function that does the same thing? If so, I thi=
nk this would be a good idea,<br><br></blockquote><div>The simplest impleme=
ntation in C++11 would be:<br><span style=3D"font-family: courier new,monos=
pace;">template<typename Functor, typename Args...><br>auto invoke(Fu=
nctor&& f, Args&&... args)<br> -> typename std::en=
able_if<<br> std::is_member_pointer&=
lt;typename std::decay<Functor>::type>::value,<br> &nbs=
p; decltype(std::mem_fn(f)(std::forward<Args>(args)...))=
<br> >::type <br>{ return std::mem_fn(f)(std::fo=
rward<Args>(args)...); }<br> <br>template<typename Functor, t=
ypename Args...><br>auto invoke(Functor&& f, Args&&... a=
rgs)<br> -> typename std::enable_if<<br>  =
; !std::is_member_pointer<typename std::decay<Functor>=
::type>::value,<br> decltype(std::fo=
rward<Functor>(f)(std::forward<Args>(args)...))<br> =
>::type <br>{ return std::forward<Functor>(f)(std::fo=
rward<Args>(args)...); }</span><br>Of course it can be implemented wi=
thout using <span style=3D"font-family: courier new,monospace;">std::mem_fn=
</span>, if you need so I can provide you such implementation.<br><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">Also, if we can define a std:=
:invoke function, I would also like a tuple_invoke function that takes a ca=
llable object f and a tuple t and calls invoke on f and the elements of t. =
If we can define std::invoke it would be easy enough to define this functio=
n using std::index_sequence.<br><br></blockquote><div>This is only partial =
solution to the problem, it is allowing only to elements of one tuple as a =
parameters to function f (you should look for boost::make_fused/unfused). U=
sing the library only based solution solution you can implement the expand =
wrapper, that will allow you to expanded tuple with normal functions argume=
nts ex. invoke(f, expand(t1), 10, exapand(t2)) (implementation of this feat=
ure can be found <a href=3D"https://github.com/tomaszkam/tlib">here</a>), b=
ut this doesnot address problems in case of initialization context (calling=
constructors, initializers list). The <a href=3D"https://groups.google.com=
/a/isocpp.org/forum/?fromgroups#%21topic/std-proposals/g1HziHt1lbo" target=
=3D"_blank">operator...</a> proposed by me address all of the case of the p=
roblems. <br><br>So I would recommend you to split the work on 2 paper=
s - one that adds std::invoke only and one for std::tuple_invoke.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_1067_27586189.1374146659638--
.
Author: tomaszkam@gmail.com
Date: Mon, 29 Jul 2013 09:48:33 -0700 (PDT)
Raw View
------=_Part_297_28479650.1375116513445
Content-Type: multipart/alternative;
boundary="----=_Part_298_3514221.1375116513445"
------=_Part_298_3514221.1375116513445
Content-Type: text/plain; charset=ISO-8859-1
I paper for adding the invoke function to the standard (it's omitted the
tuple_invoke - as I think it should go separate proposal). The paper itself
can be found in attachment, but up to date version is also on my github.<https://github.com/tomaszkam/proposals/blob/master/A%20proposal%20to%20add%20invoke%20function%20template.html>
The only design decision to take while writing up the proposal is to decide
if the invoke function should be constexpr. I decided to not impose it, to
be consistent with rest of <functional> header, but I think there should be
paper to add constexpr consistently, especially when, with the relaxation
of constexpr function requirements, most of STL algorithm can be made
constexpr.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_298_3514221.1375116513445
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
I paper for adding the invoke function to the standard (it's omitted the tu=
ple_invoke - as I think it should go separate proposal). The paper itself c=
an be found in attachment, but up to date version is also on my <a href=3D"=
https://github.com/tomaszkam/proposals/blob/master/A%20proposal%20to%20add%=
20invoke%20function%20template.html">github.</a><br><br>The only design dec=
ision to take while writing up the proposal is to decide if the invoke func=
tion should be constexpr. I decided to not impose it, to be consistent with=
rest of <functional> header, but I think there should be paper to ad=
d constexpr consistently, especially when, with the relaxation of constexpr=
function requirements, most of STL algorithm can be made constexpr. <br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_298_3514221.1375116513445--
------=_Part_297_28479650.1375116513445
Content-Type: text/html; charset=UTF-8;
name="A proposal to add invoke function template.html"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="A proposal to add invoke function template.html"
X-Attachment-Id: 8758b686-d054-4817-93a6-e3fd7673622e
Content-ID: <8758b686-d054-4817-93a6-e3fd7673622e>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/htm=
l4/strict.dtd">
<html><head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3DUTF-8">
<style type=3D"text/css">
pre {margin-left:20pt; }
pre > i {
font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
font-style:italic;
}
code > i {
font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
font-style:italic;
}
pre > em {
font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
font-style:italic;
}
code > em {
font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
font-style:italic;
}
body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }
p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }
code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
border: 1px solid #E1E28E; }
p.function { }
..attribute { margin-left: 2em; }
..attribute dt { float: left; font-style: italic;
padding-right: 1ex; }
..attribute dd { margin-left: 0em; }
blockquote.std { color: #000000; background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
color: #000000; background-color: #FFEBFF;
border: 1px solid #ECD7EC;
padding-left: 0.5empadding-right: 0.5em; ; }
blockquote.stdins { text-decoration: underline;
color: #000000; background-color: #C8FFC8;
border: 1px solid #B3EBB3; padding: 0.5em; }
table.header { border: 0px; border-spacing: 0;
margin-left: 0px; font-style: normal; }
table { border: 1px solid black; border-spacing: 0px;
margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
padding-left: 0.4em; border: none;=20
padding-right: 0.4em; border: none; }
td { text-align: left; vertical-align: top;
padding-left: 0.4em; border: none;
padding-right: 0.4em; border: none; }
</style>
<title>A proposal to add invoke function template</title>
<script type=3D"text/javascript">$(function() {
var next_id =3D 0
function find_id(node) {
// Look down the first children of 'node' until we find one
// with an id. If we don't find one, give 'node' an id and
// return that.
var cur =3D node[0];
while (cur) {
if (cur.id) return curid;
if (cur.tagName =3D=3D 'A' && cur.name)
return cur.name;
cur =3D cur.firstChild;
};
// No id.
node.attr('id', 'gensection-' + next_id++);
return node.attr('id');
};
// Put a table of contents in the #toc nav.
// This is a list of <ol> elements, where toc[N] is the list for
// the current sequence of <h(N+2)> tags. When a header of an
// existing level is encountered, all higher levels are popped,
// and an <li> is appended to the level
var toc =3D [$("<ol/>")];
$(':header').not('h1').each(function() {
var header =3D $(this);
// For each <hN> tag, add a link to the toc at the appropriate
// level. When toc is one element too short, start a new list
var levels =3D {H2: 0, H3: 1, H4: 2, H5: 3, H6: 4};
var level =3D levels[this.tagName];
if (typeof level =3D=3D 'undefined') {
throw 'Unexpected tag: ' + this.tagName;
}
// Truncate to the new level.
toc.splice(level + 1, toc.length);
if (toc.length < level) {
// Omit TOC entries for skipped header levels.
return;
}
if (toc.length =3D=3D level) {
// Add a <ol> to the previous level's last <li> and push
// it into the array.
var ol =3D $('<ol/>')
toc[toc.length - 1].children().last().append(ol);
toc.push(ol);
}
var header_text =3D header.text();
toc[toc.length - 1].append(
$('<li/>').append($('<a href=3D"#' + find_id(header) + '"/>')
.text(header_text)));
});
$('#toc').append(toc[0]);
})
</script>
</head>
<body>
<table class=3D"header"><tbody>
<tr>
<th>Document number: <th> <td></td>
</tr>
<tr>
<th>Date: <th> <td>2013-07-21</td>
</tr>
<tr>
<th>Project: <th> <td>Programming Language C++, Library Work=
ing Group</td>
</tr>
<tr>
<th>Reply-to: <th> <td><address>Tomasz Kami=C5=84ski <tom=
aszkam at gmail dot com></address></td>
</tr>
</tbody></table>
<h1><a name=3D"title">A proposal to add invoke function template</a></h1>
<h2><a name=3D"intro">Introduction</a></h2>
<p>The aim of this proposal is to introduce the function template <code>inv=
oke</code> that models <code><em>INVOKE</em></code> expression.</p>
<!--h2><a name=3D"toc">Table of contents</a></h2-->
<h2><a name=3D"motivation">Motivation and Scope</a></h2>
<p>Although the behaviour of the <code><em>INVOKE</em></code> expression ma=
y be reproduced by combination of the existing standard library components,=
separate treatment of the functors and member pointers is required in such=
solutions.</p>
<h3><a name=3D"motivation.deref-example"><code>deref_fn</code> example</a><=
/h3>
<p>As example, please consider the <code>deref_fn</code> wrapper, that shou=
ld accept any callable object <code>f</code> and returns a functor that inv=
okes provided callable and dereferences the result.</p>
<p>Using existing C++14 standard facilities <code>deref_fn</code> function =
may be implemented as:</p>
<pre>
template<typename F, std::enable_if_t<!std::is_member_pointer<st=
d::decay_t<F>>{}, int> =3D=3D 0>
auto deref_fn(F&& f)=20
{=20
return [f](auto&&... args) { return *f(std::forward<decltype=
(args)>(args)...); };
}=20
template<typename F, std::enable_if_t<std::is_member_pointer<std=
::decay_t<F>>{}, int> =3D=3D 0>
auto deref_fn(F&& f)
{=20
return [mf =3D std::mem_fn(f)](auto&&... args) { return *mf(std=
::forward<decltype(args)>(args)...); };
}
</pre>
<p>Proposed <code>invoke</code> function allow simpler implementation, that=
does not resort to use of SFINAE function overloading:</p>
<pre>
template<typename F>
auto deref_fn(F&& f)=20
{=20
return [f](auto&&... args) { return *std::invoke(f, std::forwar=
d<decltype(args)>(args)...); };
}
</pre>
<h2><a name=3D"design">Design Decisions</a></h2>
<p>Although there is possibility to implement standard conforming <code>inv=
oke</code> function template as a <code>constexpr</code> function, the prop=
osed wording does not require such implementation.
The main reason is to left it consistent with existing standard function ob=
jects, that could have such definition, like <code>std::mem_fn</code>, <cod=
e>std::reference_wrapper</code> and operator wrappers.=20
Furthermore imposing such requirement will block the implementation of <cod=
e>invoke</code> that refers to <code>std::mem_fn</code>.</p>
<p>This proposal assumes that <code>constexpr</code> addition to the <code>=
<functional></code> header would be applied consistently by a separat=
e proposal.</p>
<p>Both <code>constexpr</code> and library based implementation are present=
ed in <a href=3D"#implementability">Implementability</a> section of the pro=
posal.</p>
<h2><a name=3D"standard">Impact On The Standard</a></h2>
<p>This proposal has no dependencies beyond a C++11 compiler and Standard L=
ibrary implementation. (It depends on perfect forwarding, <code>decltype</c=
ode> and trailing return types.)</p>
<p>Nothing depends on this proposal.</p>
<h2><a name=3D"wording">Proposed wording</a></h2>
<p>After the declaration of <code>binary_function</code> in the section 20.=
10 [function.objects]/2 (Header <code><functional></code> synopsis), =
add:
<blockquote class=3D"stdins">=20
<pre> // 20.10.3, <em>invoke</em>
template <class F, class... Args> typename result_of<F&&=
(ArgTypes&&...)>::type invoke(F&& f, Args&&... a=
rgs);
template <class R, class F, class... Args> R invoke(F&& f, =
Args&&... args);
</pre>
=20
</blockquote>
<p>After paragraph 20.10.2 Requirements [func.require], insert a new paragr=
aph. (Chapter [refwrap] (Class template <code>reference_wrapper</code>) bec=
omes 20.10.?)</p>
=20
<blockquote class=3D"stdins">=20
<h4><a name=3D"invoke">20.10.3 Function template <code>invoke</code> <span =
style=3D"float:right">[invoke]</span></a></h4>
<pre> template <class F, class... Args>
typename result_of<F&&(ArgTypes&&...)>::type invo=
ke(F&& f, Args&&... args);
</pre>
<dl class=3D"attribute">
<dt>Returns:</dt> <dd><p><code><em>INVOKE</em>(std::forward<F>(f)=
, std::forward<Args>(args)...)</code> ([func.require] 20.10.2).</p> <=
/dd>
</dl>
<pre> template <class R, class F, class... Args>
R invoke(F&& f, Args&&... args);
</pre>
<dl class=3D"attribute">
<dt>Returns:</dt> <dd><p><code><em>INVOKE</em>(std::forward<F>(f)=
, std::forward<Args>(args)..., R)</code> ([func.require] 20.10.2).</p=
> </dd>
</dl>
=20
</blockquote>
<h2><a name=3D'implementability'>Implementability</a></h2>
<p>Proposed <code>invoke</code> function template may be implemented in ter=
ms of existing C++11 standard library components:</p>
<pre>
template<typename Functor, typename... Args>
typename std::enable_if<
std::is_member_pointer<typename std::decay<Functor>::type>:=
:value,
typename std::result_of<Functor&&(Args&&...)>::ty=
pe
>::type invoke(Functor&& f, Args&&... args)
{=20
return std::mem_fn(f)(std::forward<Args>(args)...);=20
}
=20
template<typename Functor, typename... Args>
typename std::enable_if<
!std::is_member_pointer<typename std::decay<Functor>::type>=
::value,
typename std::result_of<Functor&&(Args&&...)>::ty=
pe
>::type invoke(Functor&& f, Args&&... args)
{=20
return std::forward<Functor>(f)(std::forward<Args>(args)...=
);=20
}
template<typename Return, typename Functor, typename... Args>
Return invoke(Functor&& f, Args&&... args)
{
return invoke(std::forward<Functor>(f), std::forward<Args>(=
args)...);
}
</pre>
<p>An <code>constexpr</code> implemenatation may be found at: <a href=3D"ht=
tps://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp">h=
ttps://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp</=
a>.</p>
<h2><a name=3D"acknowledgements">Acknowledgements</a></h2>
<p>Joe Gottman originally proposed <code>invoke</code> function in discussi=
on group <a href=3D"https://groups.google.com/a/isocpp.org/forum/?fromgroup=
s#!topic/std-proposals/InJClAiLXcI">ISO C++ Standard - Future Proposals</a>=
..</p>
<!--p>... offered many useful suggestions and corrections to the proposal.<=
/p-->
<h2><a name=3D"literature">References</a></h2>
<ol>
<li>Tomasz Kami=C5=84ski, Implementation of invoke function (<a href=3D"htt=
ps://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp">ht=
tps://github.com/tomaszkam/proposals/blob/master/invoke/invoke_cpp11.hpp</a=
>)</li>
</ol>
</body></html>
------=_Part_297_28479650.1375116513445--
.