Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I also think there is no direct way to define the template parameters and function arguments of a single, primary template definition such that <code>T</code> can be deduced in all the different situations (function pointer, lambda expression, <code>std::function</code> argument etc.).</p> <p>I would therefore recommend that you follow the approach suggested at the end of your question. Indeed neither <code>std::function</code> nor the tools offered by Boost (as far as I know) will easily enable this, though.</p> <p>What I use (and I learnt that from other SO posts in the past), is a rather complicated template <code>function_traits</code> with specializations for all the different cases. My definition is this:</p> <pre><code>template &lt;typename T&gt; struct function_traits : public function_traits&lt;decltype(&amp;T::operator())&gt; { }; template &lt;typename Return, typename... Args&gt; struct function_traits&lt;Return(Args...)&gt; { typedef std::size_t size_type; typedef Return result_type; typedef result_type function_type(Args...); static constexpr size_type arity = sizeof...(Args); template &lt;size_type index&gt; struct arg { typedef typename std::tuple_element&lt;index,std::tuple&lt;Args...&gt;&gt;::type type; }; static constexpr bool value = true; }; template &lt;typename Return, typename... Args&gt; struct function_traits&lt;Return(*)(Args...)&gt; : function_traits&lt;Return(Args...)&gt; { }; template &lt;typename Return, typename... Args&gt; struct function_traits&lt;Return(&amp;)(Args...)&gt; : function_traits&lt;Return(Args...)&gt; { }; template &lt;typename Class, typename Return, typename... Args&gt; struct function_traits&lt;Return(Class::*)(Args...)&gt; : function_traits&lt;Return(Args...)&gt; { }; template &lt;typename Class, typename Return, typename... Args&gt; struct function_traits&lt;Return(Class::*)(Args...) volatile&gt; : function_traits&lt;Return(Args...)&gt; { }; template &lt;typename Class, typename Return, typename... Args&gt; struct function_traits&lt;Return(Class::*)(Args...) const&gt; : function_traits&lt;Return(Args...)&gt; { }; template &lt;typename Class, typename Return, typename... Args&gt; struct function_traits&lt;Return(Class::*)(Args...) const volatile&gt; : function_traits&lt;Return(Args...)&gt; { }; </code></pre> <p>To make using this even more convenient, you may want to define <code>using</code>-aliases:</p> <pre><code>template &lt;typename Fun&gt; using result_of = typename function_traits&lt;Fun&gt;::result_type; template &lt;typename Fun, std::size_t index&gt; using arg = typename function_traits&lt;Fun&gt;::template arg&lt;index&gt;::type; </code></pre> <p>With all these definitions (which in the below, I assume you put into a separate header <code>more_type_traits.hpp</code>), you can then easily define your wrapper function as follows:</p> <pre><code>#include &lt;iostream&gt; #include &lt;functional&gt; #include &lt;type_traits&gt; #include "more_type_traits.hpp" template &lt;typename Fun&gt; using noref = typename std::remove_reference&lt;Fun&gt;::type; template &lt;typename Fun&gt; result_of&lt;noref&lt;Fun&gt;&gt; fun(Fun &amp;&amp;argfun) { // Default-initialize the first argument arg&lt;noref&lt;Fun&gt;,0&gt; arg {}; // Call the function return argfun(arg); } </code></pre> <p>The below (which is basically copied from your code) then compiles and works for me:</p> <pre><code>void f1(int i) { std::cout &lt;&lt; "f1(" &lt;&lt; i &lt;&lt; ')' &lt;&lt; std::endl; } struct f2_t { void operator()(int i) { std::cout &lt;&lt; "f2(" &lt;&lt; i &lt;&lt; ')' &lt;&lt; std::endl; } }; int main() { fun(f1); f2_t f2; fun(f2); std::function&lt;void(int)&gt; funobj = [](int i) { std::cout &lt;&lt; "funobj(" &lt;&lt; i &lt;&lt; ')' &lt;&lt; std::endl; }; fun(funobj); fun( [](int i) { std::cout &lt;&lt; "lambda(" &lt;&lt; i &lt;&lt; ')' &lt;&lt; std::endl; } ); return 0; } </code></pre> <p>Clearly, the definition of <code>function_traits</code> is complicated, because many different specializations are required. But it's worth the effort if you want to make function wrapping convenient.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload