Skip to content

Commit d34af42

Browse files
jensmaurertkoeppe
authored andcommitted
P2255R2 A type trait to detect reference binding to temporary
1 parent 6fc76aa commit d34af42

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

source/support.tex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,7 @@
674674
#define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // also in \libheader{ranges}
675675
#define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility}
676676
#define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory}
677+
#define @\defnlibxname{cpp_lib_reference_from_temporary}@ 202202L // also in \libheader{type_traits}
677678
#define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // also in \libheader{type_traits}
678679
#define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // also in \libheader{functional}, \libheader{type_traits}
679680
#define @\defnlibxname{cpp_lib_robust_nonmodifying_seq_ops}@ 201304L // also in \libheader{algorithm}

source/utilities.tex

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,11 @@
872872
\begin{codeblock}
873873
!is_convertible_v<U1, T1> || !is_convertible_v<U2, T2>
874874
\end{codeblock}
875+
This constructor is defined as deleted if
876+
\tcode{reference_constructs_from_temporary_v<first_type, U1\&\&>}
877+
is \tcode{true} or
878+
\tcode{reference_constructs_from_temporary_v<second_type, U2\&\&>}
879+
is \tcode{true}.
875880
\end{itemdescr}
876881

877882
\indexlibraryctor{pair}%
@@ -909,6 +914,12 @@
909914
!is_convertible_v<decltype(get<0>(@\exposid{FWD}@(p))), T1> ||
910915
!is_convertible_v<decltype(get<1>(@\exposid{FWD}@(p))), T2>
911916
\end{codeblock}
917+
The constructor is defined as deleted if
918+
\begin{codeblock}
919+
reference_constructs_from_temporary_v<first_type, decltype(get<0>(@\exposid{FWD}@(p)))> ||
920+
reference_constructs_from_temporary_v<second_type, decltype(get<1>(@\exposid{FWD}@(p)))>
921+
\end{codeblock}
922+
is \tcode{true}.
912923
\end{itemdescr}
913924

914925
\indexlibraryctor{pair}%
@@ -936,6 +947,11 @@
936947
\tcode{std::forward<U>(x)}.) This form of construction, whereby constructor
937948
arguments for \tcode{first} and \tcode{second} are each provided in a separate
938949
\tcode{tuple} object, is called \defn{piecewise construction}.
950+
\begin{note}
951+
If a data member of \tcode{pair} is of reference type and
952+
its initialization binds it to a temporary object,
953+
the program is ill-formed\iref{class.base.init}.
954+
\end{note}
939955
\end{itemdescr}
940956

941957
\indexlibrarymember{operator=}{pair}%
@@ -1731,6 +1747,11 @@
17311747
\begin{codeblock}
17321748
!conjunction_v<is_convertible<UTypes, Types>...>
17331749
\end{codeblock}
1750+
This constructor is defined as deleted if
1751+
\begin{codeblock}
1752+
(reference_constructs_from_temporary_v<Types, UTypes\&\&> || ...)
1753+
\end{codeblock}
1754+
is \tcode{true}.
17341755
\end{itemdescr}
17351756

17361757
\indexlibraryctor{tuple}%
@@ -1806,6 +1827,11 @@
18061827
\begin{codeblock}
18071828
!(is_convertible_v<decltype(get<I>(@\exposid{FWD}@(u))), Types> && ...)
18081829
\end{codeblock}
1830+
The constructor is defined as deleted if
1831+
\begin{codeblock}
1832+
(reference_constructs_from_temporary_v<Types, decltype(get<I>(@\exposid{FWD}@(u)))> || ...)
1833+
\end{codeblock}
1834+
is \tcode{true}.
18091835
\end{itemdescr}
18101836

18111837
\indexlibraryctor{tuple}%
@@ -1843,6 +1869,12 @@
18431869
!is_convertible_v<decltype(get<0>(@\exposid{FWD}@(u))), @$\tcode{T}_0$@> ||
18441870
!is_convertible_v<decltype(get<1>(@\exposid{FWD}@(u))), @$\tcode{T}_1$@>
18451871
\end{codeblock}
1872+
The constructor is defined as deleted if
1873+
\begin{codeblock}
1874+
reference_constructs_from_temporary_v<@$\tcode{T}_0$@, decltype(get<0>(@\exposid{FWD}@(u)))> ||
1875+
reference_constructs_from_temporary_v<@$\tcode{T}_1$@, decltype(get<1>(@\exposid{FWD}@(u)))>
1876+
\end{codeblock}
1877+
is \tcode{true}.
18461878
\end{itemdescr}
18471879

18481880
\indexlibraryctor{tuple}%
@@ -2404,6 +2436,13 @@
24042436
\end{itemdecl}
24052437

24062438
\begin{itemdescr}
2439+
\pnum
2440+
\mandates
2441+
If \tcode{tuple_size_v<remove_reference_t<Tuple>>} is 1,
2442+
then
2443+
\tcode{reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))>}
2444+
is \tcode{false}.
2445+
24072446
\pnum
24082447
\effects
24092448
Given the exposition-only function:
@@ -16393,6 +16432,11 @@
1639316432
if \tcode{R} is \cv{}~\keyword{void}, otherwise
1639416433
\tcode{\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$)} implicitly converted
1639516434
to \tcode{R}.
16435+
If
16436+
\tcode{reference_converts_from_temporary_v<R, decltype(\placeholdernc{INVOKE}(f, t$_1$, t$_2$, $\dotsc$, t$_N$))>}
16437+
is \tcode{true},
16438+
\tcode{\placeholdernc{INVOKE}<R>(f, t$_1$, t$_2$, $\dotsc$, t$_N$)}
16439+
is ill-formed.
1639616440

1639716441
\pnum
1639816442
\indextext{call wrapper}%
@@ -19554,6 +19598,9 @@
1955419598

1955519599
template<class T> struct has_unique_object_representations;
1955619600

19601+
template<class T, class U> struct reference_constructs_from_temporary;
19602+
template<class T, class U> struct reference_converts_from_temporary;
19603+
1955719604
// \ref{meta.unary.prop.query}, type property queries
1955819605
template<class T> struct alignment_of;
1955919606
template<class T> struct rank;
@@ -19826,6 +19873,12 @@
1982619873
template<class T>
1982719874
inline constexpr bool has_unique_object_representations_v
1982819875
= has_unique_object_representations<T>::value;
19876+
template<class T, class U>
19877+
inline constexpr bool @\libglobal{reference_constructs_from_temporary_v}@
19878+
= reference_constructs_from_temporary<T, U>::value;
19879+
template<class T, class U>
19880+
inline constexpr bool @\libglobal{reference_converts_from_temporary_v}@
19881+
= reference_converts_from_temporary<T, U>::value;
1982919882

1983019883
// \ref{meta.unary.prop.query}, type property queries
1983119884
template<class T>
@@ -20081,6 +20134,24 @@
2008120134
in the context of the corresponding definition
2008220135
notwithstanding the restrictions of~\ref{declval}.
2008320136

20137+
\pnum
20138+
For the purpose of defining the templates in this subclause,
20139+
let \tcode{\placeholdernc{VAL}<T>} for some type \tcode{T} be
20140+
an expression defined as follows:
20141+
\begin{itemize}
20142+
\item
20143+
If \tcode{T} is a reference or function type,
20144+
\tcode{\placeholdernc{VAL}<T>} is an expression
20145+
with the same type and value category as \tcode{declval<T>()}.
20146+
\item
20147+
Otherwise, \tcode{\placeholdernc{VAL}<T>} is a prvalue
20148+
that initially has type \tcode{T}.
20149+
\begin{note}
20150+
If \tcode{T} is cv-qualified,
20151+
the cv-qualification is subject to adjustment\iref{expr.type}.
20152+
\end{note}
20153+
\end{itemize}
20154+
2008420155
\begin{libreqtab3b}{Type property predicates}{meta.unary.prop}
2008520156
\\ \topline
2008620157
\lhdr{Template} & \chdr{Condition} & \rhdr{Preconditions} \\ \capsep
@@ -20492,6 +20563,25 @@
2049220563
\tcode{T} shall be a complete type, \cv{}~\keyword{void}, or
2049320564
an array of unknown bound. \\ \rowsep
2049420565

20566+
\indexlibraryglobal{reference_constructs_from_temporary}%
20567+
\tcode{template<class T, class U>}\br
20568+
\tcode{struct reference_constructs_from_temporary;} &
20569+
\tcode{conjunction_v<is_reference<T>, is_constructible<T, U>>}
20570+
is \tcode{true}, and
20571+
the initialization \tcode{T t(\exposidnc{VAL}<U>);} binds \tcode{t} to
20572+
a temporary object whose lifetime is extended\iref{class.temporary}. &
20573+
\tcode{T} and \tcode{U} shall be
20574+
complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep
20575+
20576+
\indexlibraryglobal{reference_converts_from_temporary}%
20577+
\tcode{template<class T, class U>}\br
20578+
\tcode{struct reference_converts_from_temporary;} &
20579+
\tcode{conjunction_v<is_reference<T>, is_convertible<U, T>>} is \tcode{true},
20580+
and the initialization \tcode{T t = \exposidnc{VAL}<U>;} binds \tcode{t} to
20581+
a temporary object whose lifetime is extended\iref{class.temporary}. &
20582+
\tcode{T} and \tcode{U} shall be
20583+
complete types, \cv{}~\keyword{void}, or arrays of unknown bound. \\ \rowsep
20584+
2049520585
\end{libreqtab3b}
2049620586

2049720587
\pnum

0 commit comments

Comments
 (0)