|
16275 | 16275 | \rSec2[meta.type.synop]{Header \tcode{<type_traits>} synopsis}
|
16276 | 16276 |
|
16277 | 16277 | \indexhdr{type_traits}%
|
| 16278 | +\indexlibrary{\idxcode{is_layout_compatible_v}}% |
16278 | 16279 | \indexlibrary{\idxcode{is_nothrow_convertible_v}}%
|
| 16280 | +\indexlibrary{\idxcode{is_pointer_interconvertible_base_of_v}}% |
16279 | 16281 | \indexlibrary{\idxcode{type_identity_t}}%
|
16280 | 16282 | \indexlibrary{\idxcode{common_reference_t}}%
|
16281 | 16283 | % FIXME: Many index entries missing.
|
|
16385 | 16387 | template<class Base, class Derived> struct is_base_of;
|
16386 | 16388 | template<class From, class To> struct is_convertible;
|
16387 | 16389 | 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; |
16388 | 16392 |
|
16389 | 16393 | template<class Fn, class... ArgTypes> struct is_invocable;
|
16390 | 16394 | template<class R, class Fn, class... ArgTypes> struct is_invocable_r;
|
|
16666 | 16670 | inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
|
16667 | 16671 | template<class From, class To>
|
16668 | 16672 | 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; |
16669 | 16678 | template<class Fn, class... ArgTypes>
|
16670 | 16679 | inline constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value;
|
16671 | 16680 | template<class R, class Fn, class... ArgTypes>
|
|
16684 | 16693 | template<class B>
|
16685 | 16694 | inline constexpr bool negation_v = negation<B>::value;
|
16686 | 16695 |
|
| 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 | + |
16687 | 16702 | // \ref{meta.const.eval}, constant evaluation context
|
16688 | 16703 | constexpr bool is_constant_evaluated() noexcept;
|
16689 | 16704 | }
|
|
17498 | 17513 | types, arrays of unknown
|
17499 | 17514 | bound, or \cv{}~\tcode{void} types. \\ \rowsep
|
17500 | 17515 |
|
| 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 | + |
17501 | 17539 | \indexlibrary{\idxcode{is_invocable}}%
|
17502 | 17540 | \tcode{template<class Fn, class... ArgTypes>}\br
|
17503 | 17541 | \tcode{struct is_invocable;} &
|
|
18315 | 18353 | is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant<!bool(B::\brk{}value)>}.
|
18316 | 18354 | \end{itemdescr}
|
18317 | 18355 |
|
| 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 | + |
18318 | 18425 | \rSec2[meta.const.eval]{Constant evaluation context}
|
18319 | 18426 | \begin{itemdecl}
|
18320 | 18427 | constexpr bool is_constant_evaluated() noexcept;
|
|
0 commit comments