Skip to content

P1317R2 Remove return type deduction in std::apply #7999

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions source/meta.tex
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@
template<class Fn, class... ArgTypes> struct is_nothrow_invocable;
template<class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;

template<class Fn, class Tuple> struct is_applicable;
template<class Fn, class Tuple> struct is_nothrow_applicable;

// \ref{meta.trans.cv}, const-volatile modifications
template<class T> struct remove_const;
template<class T> struct remove_volatile;
Expand Down Expand Up @@ -348,6 +351,7 @@
template<class... T> struct common_reference;
template<class T> struct underlying_type;
template<class Fn, class... ArgTypes> struct invoke_result;
template<class Fn, class Tuple> struct apply_result;
template<class T> struct unwrap_reference;
template<class T> struct unwrap_ref_decay;

Expand All @@ -369,6 +373,8 @@
using @\libglobal{underlying_type_t}@ = typename underlying_type<T>::type;
template<class Fn, class... ArgTypes>
using @\libglobal{invoke_result_t}@ = typename invoke_result<Fn, ArgTypes...>::type;
template<class Fn, class Tuple>
using @\libglobal{apply_result_t}@ = typename apply_result<Fn, Tuple>::type;
template<class T>
using unwrap_reference_t = typename unwrap_reference<T>::type;
template<class T>
Expand Down Expand Up @@ -575,6 +581,11 @@
template<class R, class Fn, class... ArgTypes>
constexpr bool is_nothrow_invocable_r_v
= is_nothrow_invocable_r<R, Fn, ArgTypes...>::value;
template<class Fn, class Tuple>
constexpr bool @\libglobal{is_applicable_v}@ = is_applicable<Fn, Tuple>::value;
template<class Fn, class Tuple>
constexpr bool @\libglobal{is_nothrow_applicable_v}@
= is_nothrow_applicable<Fn, Tuple>::value;

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

\pnum
Let \tcode{\placeholdernc{ELEMS-OF}(T)} be the parameter pack
\tcode{get<\exposid{N}>(declval<T>())}, where \exposid{N} is the pack of
\tcode{size_t} template arguments of the specialization of
\tcode{index_sequence} denoted by
\tcode{make_index_sequence<tuple_size_v<remove_reference_t<T>>>}.

\rSec3[meta.unary.cat]{Primary type categories}

\pnum
Expand Down Expand Up @@ -1588,6 +1606,27 @@
is known not to throw any exceptions\iref{expr.unary.noexcept} &
\tcode{Fn}, \tcode{R}, and all types in the template parameter pack \tcode{ArgTypes}
shall be complete types, \cv{}~\keyword{void}, or
arrays of unknown bound. \\ \rowsep

\indexlibraryglobal{is_applicable}%
\tcode{template<class Fn, class Tuple>}\br
\tcode{struct is_applicable;} &
\tcode{\exposconcept{tuple-like}<Tuple>} is \tcode{true} and
the expression
\tcode{\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...)}
is well-formed when treated as an unevaluated operand. &
\tcode{Fn} and \tcode{Tuple}
shall be complete types, \cv{}~\keyword{void}, or
arrays of unknown bound. \\ \rowsep

\indexlibraryglobal{is_nothrow_applicable}%
\tcode{template<class Fn, class Tuple>}\br
\tcode{struct is_nothrow_applicable;} &
\tcode{is_applicable_v<}\br\tcode{Fn, Tuple>} is \tcode{true} and
the expression \tcode{\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...)}
is known not to throw any exceptions\iref{expr.unary.noexcept}. &
\tcode{Fn} and \tcode{Tuple}
shall be complete types, \cv{}~\keyword{void}, or
arrays of unknown bound. \\
\end{libreqtab3f}

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

\tcode{template<class Fn, class Tuple>}\br
\tcode{struct \libglobal{apply_result};}
&
If \tcode{\exposconcept{tuple-like}<Tuple>} is \tcode{true}
and the expression
\tcode{\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...)}\iref{func.require}
is well-formed
when treated as an unevaluated operand\iref{term.unevaluated.operand},
the member typedef \tcode{type} denotes the type
\tcode{decltype(\placeholdernc{INVOKE}(declval<Fn>(), \placeholdernc{ELEMS-OF}(Tuple)...))};
otherwise, there shall be no member \tcode{type}.
Access checking is performed as if in a context unrelated to \tcode{Fn}
and \tcode{Tuple}.
Only the validity of the immediate context of the expression is considered.
\begin{note}
The compilation of the expression can result in side effects
such as the instantiation of class template specializations
and function template specializations,
the generation of implicitly-defined functions, and so on.
Such side effects are not in the ``immediate context''
and can result in the program being ill-formed.
\end{note}
\expects
\tcode{Fn} and \tcode{Tuple} are complete types, \cv{}~\keyword{void},
or arrays of unknown bound.\\ \rowsep

\tcode{template<class T>} \tcode{struct \libglobal{unwrap_reference};}
&
If \tcode{T} is
Expand Down
15 changes: 4 additions & 11 deletions source/utilities.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1569,7 +1569,8 @@

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

template<class T, @\exposconceptnc{tuple-like}@ Tuple>
constexpr T make_from_tuple(Tuple&& t);
Expand Down Expand Up @@ -2688,7 +2689,8 @@
\indexlibraryglobal{apply}%
\begin{itemdecl}
template<class F, @\exposconcept{tuple-like}@ Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(@\seebelow@);
constexpr apply_result_t<F, Tuple> apply(F&& f, Tuple&& t)
noexcept(is_nothrow_applicable_v<F, Tuple>);
\end{itemdecl}

\begin{itemdescr}
Expand All @@ -2709,15 +2711,6 @@
return @\placeholdernc{apply-impl}@(std::forward<F>(f), std::forward<Tuple>(t),
make_index_sequence<tuple_size_v<remove_reference_t<Tuple>>>{});
\end{codeblock}

\pnum
\remarks
Let \tcode{I} be the pack
\tcode{0, 1, $\dotsc$, (tuple_size_v<remove_reference_t<Tuple>> - 1)}.
The exception specification is equivalent to:
\begin{codeblock}
noexcept(invoke(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...))
\end{codeblock}
\end{itemdescr}

\indexlibraryglobal{make_from_tuple}%
Expand Down