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 />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
&nbsp;<br />
&nbsp;<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.&nbsp; 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?&nbsp; 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&lt;typename Functor, typename Args...&gt;<br>auto invoke(Fu=
nctor&amp;&amp; f, Args&amp;&amp;... args)<br>&nbsp; -&gt; typename std::en=
able_if&lt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::is_member_pointer&=
lt;typename std::decay&lt;Functor&gt;::type&gt;::value,<br>&nbsp;&nbsp;&nbs=
p;&nbsp; &nbsp; decltype(std::mem_fn(f)(std::forward&lt;Args&gt;(args)...))=
<br>&nbsp;&nbsp;&nbsp;&nbsp; &gt;::type <br>{ return std::mem_fn(f)(std::fo=
rward&lt;Args&gt;(args)...); }<br>&nbsp;<br>template&lt;typename Functor, t=
ypename Args...&gt;<br>auto invoke(Functor&amp;&amp; f, Args&amp;&amp;... a=
rgs)<br>&nbsp; -&gt; typename std::enable_if&lt;<br>&nbsp;&nbsp;&nbsp;&nbsp=
;&nbsp;&nbsp; !std::is_member_pointer&lt;typename std::decay&lt;Functor&gt;=
::type&gt;::value,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decltype(std::fo=
rward&lt;Functor&gt;(f)(std::forward&lt;Args&gt;(args)...))<br>&nbsp;&nbsp;=
&nbsp;&nbsp; &gt;::type <br>{ return std::forward&lt;Functor&gt;(f)(std::fo=
rward&lt;Args&gt;(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.&nbsp;<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 />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
&nbsp;<br />
&nbsp;<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 &lt;functional&gt; 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 />
&nbsp;<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; 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 />
&nbsp;<br />
&nbsp;<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:&nbsp;&nbsp;<th> <td></td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;<th> <td>2013-07-21</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;<th> <td>Programming Language C++, Library Work=
ing Group</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;<th> <td><address>Tomasz Kami=C5=84ski &lt;tom=
aszkam at gmail dot com&gt;</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&lt;typename F, std::enable_if_t&lt;!std::is_member_pointer&lt;st=
d::decay_t&lt;F&gt;&gt;{}, int&gt; =3D=3D 0&gt;
  auto deref_fn(F&amp;&amp; f)=20
  {=20
    return [f](auto&amp;&amp;... args) { return *f(std::forward&lt;decltype=
(args)&gt;(args)...); };
  }=20

  template&lt;typename F, std::enable_if_t&lt;std::is_member_pointer&lt;std=
::decay_t&lt;F&gt;&gt;{}, int&gt; =3D=3D 0&gt;
  auto deref_fn(F&amp;&amp; f)
  {=20
    return [mf =3D std::mem_fn(f)](auto&amp;&amp;... args) { return *mf(std=
::forward&lt;decltype(args)&gt;(args)...); };
  }
</pre>

<p>Proposed <code>invoke</code> function allow simpler implementation, that=
 does not resort to use of SFINAE function overloading:</p>
<pre>
  template&lt;typename F&gt;
  auto deref_fn(F&amp;&amp; f)=20
  {=20
    return [f](auto&amp;&amp;... args) { return *std::invoke(f, std::forwar=
d&lt;decltype(args)&gt;(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>=
&lt;functional&gt;</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>&lt;functional&gt;</code> synopsis), =
add:

<blockquote class=3D"stdins">=20
<pre>  // 20.10.3, <em>invoke</em>
  template &lt;class F, class... Args&gt; typename result_of&lt;F&amp;&amp;=
(ArgTypes&amp;&amp;...)&gt;::type invoke(F&amp;&amp; f, Args&amp;&amp;... a=
rgs);
  template &lt;class R, class F, class... Args&gt; R invoke(F&amp;&amp; f, =
Args&amp;&amp;... 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 &lt;class F, class... Args&gt;
    typename result_of&lt;F&amp;&amp;(ArgTypes&amp;&amp;...)&gt;::type invo=
ke(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
  <dl class=3D"attribute">
    <dt>Returns:</dt> <dd><p><code><em>INVOKE</em>(std::forward&lt;F&gt;(f)=
, std::forward&lt;Args&gt;(args)...)</code> ([func.require] 20.10.2).</p> <=
/dd>
  </dl>

<pre>  template &lt;class R, class F, class... Args&gt;
    R invoke(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
  <dl class=3D"attribute">
    <dt>Returns:</dt> <dd><p><code><em>INVOKE</em>(std::forward&lt;F&gt;(f)=
, std::forward&lt;Args&gt;(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&lt;typename Functor, typename... Args&gt;
  typename std::enable_if&lt;
    std::is_member_pointer&lt;typename std::decay&lt;Functor&gt;::type&gt;:=
:value,
    typename std::result_of&lt;Functor&amp;&amp;(Args&amp;&amp;...)&gt;::ty=
pe
  &gt;::type invoke(Functor&amp;&amp; f, Args&amp;&amp;... args)
  {=20
    return std::mem_fn(f)(std::forward&lt;Args&gt;(args)...);=20
  }
  =20
  template&lt;typename Functor, typename... Args&gt;
  typename std::enable_if&lt;
    !std::is_member_pointer&lt;typename std::decay&lt;Functor&gt;::type&gt;=
::value,
    typename std::result_of&lt;Functor&amp;&amp;(Args&amp;&amp;...)&gt;::ty=
pe
  &gt;::type invoke(Functor&amp;&amp; f, Args&amp;&amp;... args)
  {=20
    return std::forward&lt;Functor&gt;(f)(std::forward&lt;Args&gt;(args)...=
);=20
  }

  template&lt;typename Return, typename Functor, typename... Args&gt;
  Return invoke(Functor&amp;&amp; f, Args&amp;&amp;... args)
  {
    return invoke(std::forward&lt;Functor&gt;(f), std::forward&lt;Args&gt;(=
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--

.