title: What should tuple_map return?
body: <p>I want to implement a generic <code>tuple_map</code> function that takes a functor and an <code>std::tuple</code>, applies the functor to every element of this tuple and returns an <code>std::tuple</code> of results. The implementation is pretty straightforward, however the question arises: what type should this function return? My implementation used <code>std::make_tuple</code>. However, <a href="https://codereview.stackexchange.com/a/201131/146724">here</a> <code>std::forward_as_tuple</code> was suggested.</p>
  
  <p>To be more specific, the implementation (handling of empty tuples is omitted for brevity):</p>
  
  <pre><code>#include &lt;cstddef&gt;
  #include &lt;tuple&gt;
  #include &lt;type_traits&gt;
  #include &lt;utility&gt;
  
  template&lt;class Fn, class Tuple, std::size_t... indices&gt;
  constexpr auto tuple_map_v(Fn fn, Tuple&amp;&amp; tuple, std::index_sequence&lt;indices...&gt;)
  {
      return std::make_tuple(fn(std::get&lt;indices&gt;(std::forward&lt;Tuple&gt;(tuple)))...);
      //          ^^^
  }
  
  template&lt;class Fn, class Tuple, std::size_t... indices&gt;
  constexpr auto tuple_map_r(Fn fn, Tuple&amp;&amp; tuple, std::index_sequence&lt;indices...&gt;)
  {
      return std::forward_as_tuple(fn(std::get&lt;indices&gt;(std::forward&lt;Tuple&gt;(tuple)))...);
      //          ^^^
  }
  
  template&lt;class Tuple, class Fn&gt;
  constexpr auto tuple_map_v(Fn fn, Tuple&amp;&amp; tuple)
  { 
      return tuple_map_v(fn, std::forward&lt;Tuple&gt;(tuple), 
          std::make_index_sequence&lt;std::tuple_size_v&lt;std::remove_reference_t&lt;Tuple&gt;&gt;&gt;{});
  }
  
  template&lt;class Tuple, class Fn&gt;
  constexpr auto tuple_map_r(Fn fn, Tuple&amp;&amp; tuple)
  { 
      return tuple_map_r(fn, std::forward&lt;Tuple&gt;(tuple), 
          std::make_index_sequence&lt;std::tuple_size_v&lt;std::remove_reference_t&lt;Tuple&gt;&gt;&gt;{});
  }
  </code></pre>
  
  <p>In the case 1 we use <code>std::make_tuple</code> which decays type of each argument (<code>_v</code> for value), and in the case 2 we use <code>std::forward_as_tuple</code> which preserves references (<code>_r</code> for reference). Both cases have their pros and cons.</p>
  
  <ol>
  <li><p>Dangling references.</p>
  
  <pre><code>auto copy = [](auto x) { return x; };
  auto const_id = [](const auto&amp; x) -&gt; decltype(auto) { return x; };
  
  auto r1 = tuple_map_v(copy, std::make_tuple(1));
  // OK, type of r1 is std::tuple&lt;int&gt;
  
  auto r2 = tuple_map_r(copy, std::make_tuple(1));
  // UB, type of r2 is std::tuple&lt;int&amp;&amp;&gt;
  
  std::tuple&lt;int&gt; r3 = tuple_map_r(copy, std::make_tuple(1));
  // Still UB
  
  std::tuple&lt;int&gt; r4 = tuple_map_r(const_id, std::make_tuple(1));
  // OK now
  </code></pre></li>
  <li><p>Tuple of references.</p>
  
  <pre><code>auto id = [](auto&amp; x) -&gt; decltype(auto) { return x; };
  
  int a = 0, b = 0;
  auto r1 = tuple_map_v(id, std::forward_as_tuple(a, b));
  // Type of r1 is std::tuple&lt;int, int&gt;
  ++std::get&lt;0&gt;(r1);
  // Increments a copy, a is still zero
  
  auto r2 = tuple_map_r(id, std::forward_as_tuple(a, b));
  // Type of r2 is std::tuple&lt;int&amp;, int&amp;&gt;
  ++std::get&lt;0&gt;(r2);
  // OK, now a = 1
  </code></pre></li>
  <li><p>Move-only types.</p>
  
  <pre><code>NonCopyable nc;
  auto r1 = tuple_map_v(id, std::forward_as_tuple(nc));
  // Does not compile without a copy constructor 
  
  auto r2 = tuple_map_r(id, std::forward_as_tuple(nc));
  // OK, type of r2 is std::tuple&lt;NonCopyable&amp;&gt;
  </code></pre></li>
  <li><p>References with <code>std::make_tuple</code>.</p>
  
  <pre><code>auto id_ref = [](auto&amp; x) { return std::reference_wrapper(x); };
  
  NonCopyable nc;
  auto r1 = tuple_map_v(id_ref, std::forward_as_tuple(nc));
  // OK now, type of r1 is std::tuple&lt;NonCopyable&amp;&gt;
  
  auto r2 = tuple_map_v(id_ref, std::forward_as_tuple(a, b));
  // OK, type of r2 is std::tuple&lt;int&amp;, int&amp;&gt;
  </code></pre></li>
  </ol>
  
  <p>(Probably, I got something wrong or missed something important.)</p>
  
  <p>It seems that <code>make_tuple</code> is the way to go: it doesn't produce dangling references and still can be forced to deduce a reference type. How would you implement <code>tuple_map</code> (and what would be the pitfalls associated with it)?</p>