title: decltype for the return type of recursive variadic function template
body: <p>Given the following code(taken from <a href="https://codereview.stackexchange.com/questions/63841/c-function-composition?newreg=25a6ddb61c3a44a38cd380d55b926f8e">here</a>):</p>
  
  <pre><code>#include &lt;cstddef&gt;
  #include &lt;type_traits&gt;
  #include &lt;tuple&gt;
  #include &lt;iostream&gt;
  #include &lt;utility&gt;
  #include &lt;functional&gt;
  
  template&lt;typename ... Fs&gt;
  struct compose_impl
  {
      compose_impl(Fs&amp;&amp; ... fs) : functionTuple(std::forward_as_tuple(fs ...)) {}
  
      template&lt;size_t N, typename ... Ts&gt;
      auto apply(std::integral_constant&lt;size_t, N&gt;, Ts&amp;&amp; ... ts) const
      {
          return apply(std::integral_constant&lt;size_t, N - 1&gt;(), std::get&lt;N&gt;  (functionTuple)(std::forward&lt;Ts&gt;(ts)...));
      }
  
      template&lt;typename ... Ts&gt;
      auto apply(std::integral_constant&lt;size_t, 0&gt;, Ts&amp;&amp; ... ts) const
      {
          return std::get&lt;0&gt;(functionTuple)(std::forward&lt;Ts&gt;(ts)...);
      }
  
      template&lt;typename ... Ts&gt;
      auto operator()(Ts&amp;&amp; ... ts) const
      {
           return apply(std::integral_constant&lt;size_t, sizeof ... (Fs) - 1&gt;(), std::forward&lt;Ts&gt;(ts)...);
      }
  
      std::tuple&lt;Fs ...&gt; functionTuple;
  };
  
  template&lt;typename ... Fs&gt;
  auto compose(Fs&amp;&amp; ... fs)
  {
       return compose_impl&lt;Fs ...&gt;(std::forward&lt;Fs&gt;(fs) ...);
  }
  
  int main ()
  {
      auto f1 = [](std::pair&lt;double,double&gt; p) {return p.first + p.second;    };
      auto f2 = [](double x) {return std::make_pair(x, x + 1.0); };
      auto f3 = [](double x, double y) {return x*y; };
      auto g = compose(f1, f2, f3);
  
      std::cout &lt;&lt; g(2.0, 3.0) &lt;&lt; std::endl;   //prints '13', evaluated as (2*3) + ((2*3)+1)
      return 0;
  }
  </code></pre>
  
  <p>The code above works in C++14. I'm having some trouble making it work for C++11. I tried to properly provide the return types for the function templates involved but without much success e.g.:</p>
  
  <pre><code>template&lt;typename... Fs&gt;
  struct compose_impl
  {
      compose_impl(Fs&amp;&amp;... fs) : func_tup(std::forward_as_tuple(fs...)) {}
  
      template&lt;size_t N, typename... Ts&gt;
      auto apply(std::integral_constant&lt;size_t, N&gt;, Ts&amp;&amp;... ts) const -&gt; decltype(std::declval&lt;typename std::tuple_element&lt;N, std::tuple&lt;Fs...&gt;&gt;::type&gt;()(std::forward&lt;Ts&gt;(ts)...))
      // -- option 2. decltype(apply(std::integral_constant&lt;size_t, N - 1&gt;(), std::declval&lt;typename std::tuple_element&lt;N, std::tuple&lt;Fs...&gt;&gt;::type&gt;()(std::forward&lt;Ts&gt;(ts)...)))
      {
           return apply(std::integral_constant&lt;size_t, N - 1&gt;(), std::get&lt;N&gt;(func_tup)(std::forward&lt;Ts&gt;(ts)...));
      }
  
      using func_type = typename std::tuple_element&lt;0, std::tuple&lt;Fs...&gt;&gt;::type;
      template&lt;typename... Ts&gt;
      auto apply(std::integral_constant&lt;size_t, 0&gt;, Ts&amp;&amp;... ts) const -&gt; decltype(std::declval&lt;func_type&gt;()(std::forward&lt;Ts&gt;(ts)...))
      {
          return std::get&lt;0&gt;(func_tup)(std::forward&lt;Ts&gt;(ts)...);
      }
  
      template&lt;typename... Ts&gt;
      auto operator()(Ts&amp;&amp;... ts) const -&gt; decltype(std::declval&lt;func_type&gt;()(std::forward&lt;Ts&gt;(ts)...))
      // -- option 2. decltype(apply(std::integral_constant&lt;size_t, sizeof...(Fs) - 1&gt;(), std::forward&lt;Ts&gt;(ts)...))
      {
          return apply(std::integral_constant&lt;size_t, sizeof...(Fs) - 1&gt;(), std::forward&lt;Ts&gt;(ts)...);
      }
  
      std::tuple&lt;Fs...&gt; func_tup;
  };
  
  template&lt;typename... Fs&gt;
  auto compose(Fs&amp;&amp;... fs) -&gt; decltype(compose_impl&lt;Fs...&gt;(std::forward&lt;Fs&gt;(fs)...))
  {
     return compose_impl&lt;Fs...&gt;(std::forward&lt;Fs&gt;(fs)...);
  }
  </code></pre>
  
  <p>For the above clang(3.5.0) gives me the following error:</p>
  
  <pre><code>func_compose.cpp:79:18: error: no matching function for call to object of type 'compose_impl&lt;(lambda at func_compose.cpp:65:15) &amp;, (lambda at func_compose.cpp:67:15) &amp;,
    (lambda at func_compose.cpp:68:15) &amp;&gt;'
  std::cout &lt;&lt; g(2.0, 3.0) &lt;&lt; std::endl;   //prints '13', evaluated as (2*3) + ((2*3)+1)
               ^
   func_compose.cpp:31:10: note: candidate template ignored: substitution failure [with Ts = &lt;double, double&gt;]: no matching function for call to object of type
    '(lambda at func_compose.cpp:65:15)'
   auto operator()(Ts&amp;&amp;... ts) /*const*/ -&gt; decltype(std::declval&lt;func_type&gt;()(std::forward&lt;Ts&gt;(ts)...))
       ^                                            ~~~
  1 error generated.
  </code></pre>
  
  <p>If I try "option 2." I get pretty much the same error.</p>
  
  <p>Apart from the fact that it looks very verbose I also cannot seem to get it right. Could anyone provide some insight in what am I doing wrong? 
  Is there any simpler way to provide the return types? </p>