Skip to content

Commit a1e2efa

Browse files
committed
P1317R2 Remove return type deduction in std::apply
This commit adds "tuple-like<Tuple> is true and" to the definition of apply_result. LWG noticed this was needed but we were unable to contact the paper author to make the change in time for plenary.
1 parent a8d9618 commit a1e2efa

File tree

2 files changed

+69
-11
lines changed

2 files changed

+69
-11
lines changed

source/meta.tex

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@
276276
template<class Fn, class... ArgTypes> struct is_nothrow_invocable;
277277
template<class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;
278278

279+
template<class Fn, class Tuple> struct is_applicable;
280+
template<class Fn, class Tuple> struct is_nothrow_applicable;
281+
279282
// \ref{meta.trans.cv}, const-volatile modifications
280283
template<class T> struct remove_const;
281284
template<class T> struct remove_volatile;
@@ -348,6 +351,7 @@
348351
template<class... T> struct common_reference;
349352
template<class T> struct underlying_type;
350353
template<class Fn, class... ArgTypes> struct invoke_result;
354+
template<class Fn, class Tuple> struct apply_result;
351355
template<class T> struct unwrap_reference;
352356
template<class T> struct unwrap_ref_decay;
353357

@@ -369,6 +373,8 @@
369373
using @\libglobal{underlying_type_t}@ = typename underlying_type<T>::type;
370374
template<class Fn, class... ArgTypes>
371375
using @\libglobal{invoke_result_t}@ = typename invoke_result<Fn, ArgTypes...>::type;
376+
template<class Fn, class Tuple>
377+
using @\libglobal{apply_result_t}@ = typename apply_result<Fn, Tuple>::type;
372378
template<class T>
373379
using unwrap_reference_t = typename unwrap_reference<T>::type;
374380
template<class T>
@@ -575,6 +581,11 @@
575581
template<class R, class Fn, class... ArgTypes>
576582
constexpr bool is_nothrow_invocable_r_v
577583
= is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;
584+
template<class Fn, class Tuple>
585+
constexpr bool @\libglobal{is_applicable_v}@ = is_applicable<Fn, Tuple>::value;
586+
template<class Fn, class Tuple>
587+
constexpr bool @\libglobal{is_nothrow_applicable_v}@
588+
= is_nothrow_applicable<Fn, Tuple>::value;
578589

579590
// \ref{meta.logical}, logical operator traits
580591
template<class... B>
@@ -639,6 +650,13 @@
639650
\tcode{true_type} if the corresponding condition is \tcode{true}, otherwise
640651
\tcode{false_type}.
641652

653+
\pnum
654+
Let \tcode{\placeholdernc{ELEMS-OF}(T)} be the parameter pack
655+
\tcode{get<\exposid{N}>(declval<T>())}, where \exposid{N} is the pack of
656+
\tcode{size_t} template arguments of the specialization of
657+
\tcode{index_sequence} denoted by
658+
\tcode{make_index_sequence<tuple_size_v<remove_reference_t<T>>>}.
659+
642660
\rSec3[meta.unary.cat]{Primary type categories}
643661

644662
\pnum
@@ -1588,6 +1606,27 @@
15881606
is known not to throw any exceptions\iref{expr.unary.noexcept} &
15891607
\tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes}
15901608
shall be complete types, \cv{}~\keyword{void}, or
1609+
arrays of unknown bound. \\ \rowsep
1610+
1611+
\indexlibraryglobal{is_applicable}%
1612+
\tcode{template<class Fn, class Tuple>}\br
1613+
\tcode{struct is_applicable;} &
1614+
\tcode{\exposconcept{tuple-like}<Tuple>} is \tcode{true} and
1615+
the expression
1616+
\tcode{\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...)}
1617+
is well-formed when treated as an unevaluated operand. &
1618+
\tcode{Fn} and \tcode{Tuple}
1619+
shall be complete types, \cv{}~\keyword{void}, or
1620+
arrays of unknown bound. \\ \rowsep
1621+
1622+
\indexlibraryglobal{is_nothrow_applicable}%
1623+
\tcode{template<class Fn, class Tuple>}\br
1624+
\tcode{struct is_nothrow_applicable;} &
1625+
\tcode{is_applicable_v<}\br\tcode{Fn, Tuple>} is \tcode{true} and
1626+
the expression \tcode{\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...)}
1627+
is known not to throw any exceptions\iref{expr.unary.noexcept}. &
1628+
\tcode{Fn} and \tcode{Tuple}
1629+
shall be complete types, \cv{}~\keyword{void}, or
15911630
arrays of unknown bound. \\
15921631
\end{libreqtab3f}
15931632

@@ -2029,6 +2068,32 @@
20292068
are complete types, \cv{}~\keyword{void}, or arrays of
20302069
unknown bound.\\ \rowsep
20312070

2071+
\tcode{template<class Fn, class Tuple>}\br
2072+
\tcode{struct \libglobal{apply_result};}
2073+
&
2074+
If \tcode{\exposconcept{tuple-like}<Tuple>} is \tcode{true}
2075+
and the expression
2076+
\tcode{\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...)}\iref{func.require}
2077+
is well-formed
2078+
when treated as an unevaluated operand\iref{term.unevaluated.operand},
2079+
the member typedef \tcode{type} denotes the type
2080+
\tcode{decltype(\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...))};
2081+
otherwise, there shall be no member \tcode{type}.
2082+
Access checking is performed as if in a context unrelated to \tcode{Fn}
2083+
and \tcode{Tuple}.
2084+
Only the validity of the immediate context of the expression is considered.
2085+
\begin{note}
2086+
The compilation of the expression can result in side effects
2087+
such as the instantiation of class template specializations
2088+
and function template specializations,
2089+
the generation of implicitly-defined functions, and so on.
2090+
Such side effects are not in the ``immediate context''
2091+
and can result in the program being ill-formed.
2092+
\end{note}
2093+
\expects
2094+
\tcode{Fn} and \tcode{Tuple} are complete types, \cv{}~\keyword{void},
2095+
or arrays of unknown bound.\\ \rowsep
2096+
20322097
\tcode{template<class T>} \tcode{struct \libglobal{unwrap_reference};}
20332098
&
20342099
If \tcode{T} is

source/utilities.tex

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1569,7 +1569,8 @@
15691569

15701570
// \ref{tuple.apply}, calling a function with a tuple of arguments
15711571
template<class F, @\exposconceptnc{tuple-like}@ Tuple>
1572-
constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(@\seebelow@);
1572+
constexpr apply_result_t<F, Tuple> apply(F&& f, Tuple&& t)
1573+
noexcept(is_nothrow_applicable_v<F, Tuple>);
15731574

15741575
template<class T, @\exposconceptnc{tuple-like}@ Tuple>
15751576
constexpr T make_from_tuple(Tuple&& t);
@@ -2688,7 +2689,8 @@
26882689
\indexlibraryglobal{apply}%
26892690
\begin{itemdecl}
26902691
template<class F, @\exposconcept{tuple-like}@ Tuple>
2691-
constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(@\seebelow@);
2692+
constexpr apply_result_t<F, Tuple> apply(F&& f, Tuple&& t)
2693+
noexcept(is_nothrow_applicable_v<F, Tuple>);
26922694
\end{itemdecl}
26932695

26942696
\begin{itemdescr}
@@ -2709,15 +2711,6 @@
27092711
return @\placeholdernc{apply-impl}@(std::forward<F>(f), std::forward<Tuple>(t),
27102712
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
27112713
\end{codeblock}
2712-
2713-
\pnum
2714-
\remarks
2715-
Let \tcode{I} be the pack
2716-
\tcode{0, 1, $\dotsc$, (tuple_size_v<remove_reference_t<Tuple>> - 1)}.
2717-
The exception specification is equivalent to:
2718-
\begin{codeblock}
2719-
noexcept(invoke(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...))
2720-
\end{codeblock}
27212714
\end{itemdescr}
27222715

27232716
\indexlibraryglobal{make_from_tuple}%

0 commit comments

Comments
 (0)