diff --git a/source/support.tex b/source/support.tex index 9495257e24..349c00602e 100644 --- a/source/support.tex +++ b/source/support.tex @@ -625,6 +625,7 @@ #define @\defnlibxname{cpp_lib_find_last}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_flat_map}@ 202207L // also in \libheader{flat_map} #define @\defnlibxname{cpp_lib_format}@ 202207L // also in \libheader{format} +#define @\defnlibxname{cpp_lib_forward_like}@ 202207L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_gcd_lcm}@ 201606L // also in \libheader{numeric} #define @\defnlibxname{cpp_lib_generic_associative_lookup}@ 201304L // also in \libheader{map}, \libheader{set} #define @\defnlibxname{cpp_lib_generic_unordered_lookup}@ 201811L diff --git a/source/utilities.tex b/source/utilities.tex index 46ec5ed5a0..e78ed9dc4a 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -55,6 +55,8 @@ constexpr T&& forward(remove_reference_t& t) noexcept; template constexpr T&& forward(remove_reference_t&& t) noexcept; + template + [[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> @\seebelow@; template constexpr remove_reference_t&& move(T&&) noexcept; template @@ -358,6 +360,57 @@ \end{example} \end{itemdescr} +\indexlibraryglobal{forward_like}% +\begin{itemdecl} +template + [[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> @\seebelow@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\begin{itemize} +\item +Let \tcode{\exposid{COPY_CONST}(A, B)} be \tcode{const B} +if \tcode{A} is a const type, otherwise \tcode{B}. +\item +Let \tcode{\exposid{OVERRIDE_REF}(A, B)} be \tcode{remove_reference_t\&\&} +if \tcode{A} is an rvalue reference type, otherwise \tcode{B\&}. +\item +Let \tcode{V} be +\begin{codeblock} +@\exposid{OVERRIDE_REF}@(T&&, @\exposid{COPY_CONST}@(remove_reference_t, remove_reference_t)) +\end{codeblock} +\end{itemize} + +\pnum +\returns +\tcode{static_cast(x)}. + +\pnum +\remarks +The return type is \tcode{V}. + +\pnum +\begin{example} +\begin{codeblock} +struct accessor { + vector* container; + decltype(auto) operator[](this auto&& self, size_t i) { + return std::forward_like((*container)[i]); + } +}; +void g() { + vector v{"a"s, "b"s}; + accessor a{&v}; + string& x = a[0]; // OK, binds to lvalue reference + string&& y = std::move(a)[0]; // OK, is rvalue reference + string const&& z = std::move(as_const(a))[1]; // OK, is \tcode{const\&\&} + string& w = as_const(a)[1]; // error: will not bind to non-const +} +\end{codeblock} +\end{example} +\end{itemdescr} + \indexlibrary{\idxcode{move}!function}% \indextext{\idxcode{move}}% \begin{itemdecl}