This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.

### 2314. `apply()` should return `decltype(auto)` and use `decay_t` before `tuple_size`

Section: 21.2.1 [intseq.general] Status: C++14 Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2017-07-05

Priority: 0

View all issues with C++14 status.

Discussion:

The example in 21.2.1 [intseq.general]/2 depicts `apply_impl()` and `apply()` as returning `auto`. This is incorrect because it will trigger decay and will not preserve `F`'s return type. For example, if invoking the functor returns `const int&`, `apply_impl()` and `apply()` will return `int`. `decltype(auto)` should be used for "perfect returning".

Additionally, this depicts `apply()` as taking `Tuple&&`, then saying "`std::tuple_size<Tuple>::value`". This is incorrect because when `apply()` is called with lvalue tuples, perfect forwarding will deduce `Tuple` to be cv `tuple&`, but 22.4.7 [tuple.helper] says that `tuple_size` handles only cv `tuple`, not references to tuples. Using `remove_reference_t` would avoid this problem, but so would `decay_t`, which has a significantly shorter name. (The additional transformations that `decay_t` does are neither beneficial nor harmful here.)

[Issaquah 2014-02-11: Move to Immediate]

Proposed resolution:

This wording is relative to N3691.

1. Edit the example code in 21.2.1 [intseq.general]/2 as indicated:

   >     template<class F, class Tuple, std::size_t... I>
   >       autodecltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
   >         return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
   >       }
   >     template<class F, class Tuple>
   >       autodecltype(auto) apply(F&& f, Tuple&& t) {
   >         using Indices = make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>;
   >         return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), Indices());
   >       }