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.
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()); }