Skip to content

Commit d3506cf

Browse files
authored
Merge 2019-07 LWG Motion 31
P0466R5 Layout-compatibility and Pointer-interconvertibility Traits Fixes #3035.
2 parents c4e3a18 + b83cb6d commit d3506cf

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

source/utilities.tex

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16275,7 +16275,9 @@
1627516275
\rSec2[meta.type.synop]{Header \tcode{<type_traits>} synopsis}
1627616276

1627716277
\indexhdr{type_traits}%
16278+
\indexlibrary{\idxcode{is_layout_compatible_v}}%
1627816279
\indexlibrary{\idxcode{is_nothrow_convertible_v}}%
16280+
\indexlibrary{\idxcode{is_pointer_interconvertible_base_of_v}}%
1627916281
\indexlibrary{\idxcode{type_identity_t}}%
1628016282
\indexlibrary{\idxcode{common_reference_t}}%
1628116283
% FIXME: Many index entries missing.
@@ -16385,6 +16387,8 @@
1638516387
template<class Base, class Derived> struct is_base_of;
1638616388
template<class From, class To> struct is_convertible;
1638716389
template<class From, class To> struct is_nothrow_convertible;
16390+
template<class T, class U> struct is_layout_compatible;
16391+
template<class Base, class Derived> struct is_pointer_interconvertible_base_of;
1638816392

1638916393
template<class Fn, class... ArgTypes> struct is_invocable;
1639016394
template<class R, class Fn, class... ArgTypes> struct is_invocable_r;
@@ -16666,6 +16670,11 @@
1666616670
inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
1666716671
template<class From, class To>
1666816672
inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value;
16673+
template<class T, class U>
16674+
inline constexpr bool is_layout_compatible_v = is_layout_compatible<T, U>::value;
16675+
template<class Base, class Derived>
16676+
inline constexpr bool is_pointer_interconvertible_base_of_v
16677+
= is_pointer_interconvertible_base_of<Base, Derived>::value;
1666916678
template<class Fn, class... ArgTypes>
1667016679
inline constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value;
1667116680
template<class R, class Fn, class... ArgTypes>
@@ -16684,6 +16693,12 @@
1668416693
template<class B>
1668516694
inline constexpr bool negation_v = negation<B>::value;
1668616695

16696+
// \ref{meta.member}, member relationships
16697+
template<class S, class M>
16698+
constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept;
16699+
template<class S1, class S2, class M1, class M2>
16700+
constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept;
16701+
1668716702
// \ref{meta.const.eval}, constant evaluation context
1668816703
constexpr bool is_constant_evaluated() noexcept;
1668916704
}
@@ -17498,6 +17513,29 @@
1749817513
types, arrays of unknown
1749917514
bound, or \cv{}~\tcode{void} types. \\ \rowsep
1750017515

17516+
\indexlibrary{\idxcode{is_layout_compatible}}%
17517+
\tcode{template<class T, class U>}\br
17518+
\tcode{struct is_layout_compatible;} &
17519+
\tcode{T} and \tcode{U} are layout-compatible\iref{basic.types} &
17520+
\tcode{T} and \tcode{U} shall be complete types,
17521+
\cv{}~\tcode{void},
17522+
or arrays of unknown bound. \\ \rowsep
17523+
17524+
\indexlibrary{\idxcode{is_pointer_interconvertible_base_of}}%
17525+
\tcode{template<class Base, class Derived>}\br
17526+
\tcode{struct is_pointer_interconvertible_base_of;} &
17527+
\tcode{Derived} is unambiguously derived from \tcode{Base}
17528+
without regard to cv-qualifiers,
17529+
and each object of type \tcode{Derived}
17530+
is pointer-interconvertible\iref{basic.compound} with
17531+
its \tcode{Base} subobject,
17532+
or \tcode{Base} and \tcode{Derived} are not unions
17533+
and name the same class type
17534+
without regard to cv-qualifiers. &
17535+
If \tcode{Base} and \tcode{Derived} are non-union class types
17536+
and are not (possibly cv-qualified versions of) the same type,
17537+
\tcode{Derived} shall be a complete type. \\ \rowsep
17538+
1750117539
\indexlibrary{\idxcode{is_invocable}}%
1750217540
\tcode{template<class Fn, class... ArgTypes>}\br
1750317541
\tcode{struct is_invocable;} &
@@ -18315,6 +18353,75 @@
1831518353
is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant<!bool(B::\brk{}value)>}.
1831618354
\end{itemdescr}
1831718355

18356+
\rSec2[meta.member]{Member relationships}
18357+
18358+
\indexlibrary{\idxcode{is_pointer_interconvertible_with_class}}
18359+
\begin{itemdecl}
18360+
template<class S, class M>
18361+
constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept;
18362+
\end{itemdecl}
18363+
18364+
\begin{itemdescr}
18365+
\pnum
18366+
\mandates \tcode{S} is a complete type.
18367+
18368+
\pnum
18369+
\returns \tcode{true} if and only if
18370+
\tcode{S} is a standard-layout type,
18371+
\tcode{M} is an object type,
18372+
\tcode{m} is not null,
18373+
and each object \tcode{s} of type \tcode{S}
18374+
is pointer-interconvertible\iref{basic.compound}
18375+
with its subobject \tcode{s.*m}.
18376+
\end{itemdescr}
18377+
18378+
\indexlibrary{\idxcode{is_corresponding_member}}
18379+
\begin{itemdecl}
18380+
template<class S1, class S2, class M1, class M2>
18381+
constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept;
18382+
\end{itemdecl}
18383+
18384+
\begin{itemdescr}
18385+
\pnum
18386+
\mandates \tcode{S1} and \tcode{S2} are complete types.
18387+
18388+
\pnum
18389+
\returns \tcode{true} if and only if
18390+
\tcode{S1} and \tcode{S2} are standard-layout types,
18391+
\tcode{M1} and \tcode{M2} are object types,
18392+
\tcode{m1} and \tcode{m2} are not null,
18393+
and \tcode{m1} and \tcode{m2} point to corresponding members of
18394+
the common initial sequence\iref{class.mem} of \tcode{S1} and \tcode{S2}.
18395+
\end{itemdescr}
18396+
18397+
\pnum
18398+
\begin{note}
18399+
The type of a pointer-to-member expression \tcode{\&C::b}
18400+
is not always a pointer to member of \tcode{C},
18401+
leading to potentially surprising results
18402+
when using these functions in conjunction with inheritance.
18403+
\begin{example}
18404+
\begin{codeblock}
18405+
struct A { int a; }; // a standard-layout class
18406+
struct B { int b; }; // a standard-layout class
18407+
struct C: public A, public B { }; // not a standard-layout class
18408+
18409+
static_assert( is_pointer_interconvertible_with_class( &C::b ) );
18410+
// Succeeds because, despite its appearance, \tcode{\&C::b} has type
18411+
// ``pointer to member of \tcode{B} of type \tcode{int}''.
18412+
static_assert( is_pointer_interconvertible_with_class<C>( &C::b ) );
18413+
// Forces the use of class \tcode{C}, and fails.
18414+
18415+
static_assert( is_corresponding_member( &C::a, &C::b ) );
18416+
// Succeeds because, despite its appearance, \tcode{\&C::a} and \tcode{\&C::b} have types
18417+
// ``pointer to member of \tcode{A} of type \tcode{int}'' and
18418+
// ``pointer to member of \tcode{B} of type \tcode{int}'', respectively.
18419+
static_assert( is_corresponding_member<C, C>( &C::a, &C::b ) );
18420+
// Forces the use of class \tcode{C}, and fails.
18421+
\end{codeblock}
18422+
\end{example}
18423+
\end{note}
18424+
1831818425
\rSec2[meta.const.eval]{Constant evaluation context}
1831918426
\begin{itemdecl}
1832018427
constexpr bool is_constant_evaluated() noexcept;

0 commit comments

Comments
 (0)