|
16519 | 16519 | template<class Base, class Derived> struct is_base_of;
|
16520 | 16520 | template<class From, class To> struct is_convertible;
|
16521 | 16521 | template<class From, class To> struct is_nothrow_convertible;
|
| 16522 | + template<class T, class U> struct is_layout_compatible; |
| 16523 | + template<class Base, class Derived> struct is_pointer_interconvertible_base_of; |
16522 | 16524 |
|
16523 | 16525 | template<class Fn, class... ArgTypes> struct is_invocable;
|
16524 | 16526 | template<class R, class Fn, class... ArgTypes> struct is_invocable_r;
|
|
16803 | 16805 | inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
|
16804 | 16806 | template<class From, class To>
|
16805 | 16807 | inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value;
|
| 16808 | + template<class T, class U> |
| 16809 | + inline constexpr bool is_layout_compatible_v = is_layout_compatible<T, U>::value; |
| 16810 | + template<class Base, class Derived> |
| 16811 | + inline constexpr bool is_pointer_interconvertible_base_of_v |
| 16812 | + = is_pointer_interconvertible_base_of<Base, Derived>::value; |
16806 | 16813 | template<class Fn, class... ArgTypes>
|
16807 | 16814 | inline constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value;
|
16808 | 16815 | template<class R, class Fn, class... ArgTypes>
|
|
16821 | 16828 | template<class B>
|
16822 | 16829 | inline constexpr bool negation_v = negation<B>::value;
|
16823 | 16830 |
|
| 16831 | + // \ref{meta.member}, member relationships |
| 16832 | + template<class S, class M> |
| 16833 | + constexpr bool |
| 16834 | + is_pointer_interconvertible_with_class(M S::*m) noexcept; |
| 16835 | + template<class S1, class S2, class M1, class M2> |
| 16836 | + constexpr bool |
| 16837 | + is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; |
| 16838 | + |
16824 | 16839 | // \ref{meta.const.eval}, constant evaluation context
|
16825 | 16840 | constexpr bool is_constant_evaluated() noexcept;
|
16826 | 16841 | }
|
|
17627 | 17642 | types, arrays of unknown
|
17628 | 17643 | bound, or \cv{}~\tcode{void} types. \\ \rowsep
|
17629 | 17644 |
|
| 17645 | +\indexlibrary{\idxcode{is_layout_compatible}}% |
| 17646 | +\tcode{template<class T, class U>}\br |
| 17647 | + \tcode{struct is_layout_compatible;} & |
| 17648 | + \tcode{T} and \tcode{U} are layout-compatible\iref{basic.types} & |
| 17649 | + \tcode{T} and \tcode{U} shall be complete types, |
| 17650 | + \cv{}~\tcode{void}, |
| 17651 | + or arrays of unknown bound. \\ \rowsep |
| 17652 | + |
| 17653 | +\indexlibrary{\idxcode{is_pointer_interconvertible_base_of}}% |
| 17654 | +\tcode{template<class Base, class Derived>}\br |
| 17655 | + \tcode{struct is_pointer_interconvertible_base_of;} & |
| 17656 | + \tcode{Derived} is unambiguously derived from \tcode{Base} |
| 17657 | + without regard to \cv{}-qualifiers, |
| 17658 | + and each object of type \tcode{Derived} |
| 17659 | + is pointer-interconvertible\iref{basic.compound} with |
| 17660 | + its \tcode{Base} subobject, |
| 17661 | + or \tcode{Base} and \tcode{Derived} are not unions |
| 17662 | + and name the same class type |
| 17663 | + without regard to \cv{}-qualifiers. & |
| 17664 | + If \tcode{Base} and \tcode{Derived} are non-union class types |
| 17665 | + and are not (possibly \cv{}-qualified versions of) the same type, |
| 17666 | + \tcode{Derived} shall be a complete type. \\ \rowsep |
| 17667 | + |
17630 | 17668 | \indexlibrary{\idxcode{is_invocable}}%
|
17631 | 17669 | \tcode{template<class Fn, class... ArgTypes>}\br
|
17632 | 17670 | \tcode{struct is_invocable;} &
|
|
18440 | 18478 | is a \oldconcept{UnaryTypeTrait} with a base characteristic of \tcode{bool_constant<!bool(B::\brk{}value)>}.
|
18441 | 18479 | \end{itemdescr}
|
18442 | 18480 |
|
| 18481 | +\rSec2[meta.member]{Member relationships} |
| 18482 | + |
| 18483 | +\indexlibrary{\idxcode{is_pointer_interconvertible_with_class}} |
| 18484 | +\begin{itemdecl} |
| 18485 | +template<class S, class M> |
| 18486 | +constexpr bool |
| 18487 | +is_pointer_interconvertible_with_class(M S::*m) noexcept; |
| 18488 | +\end{itemdecl} |
| 18489 | + |
| 18490 | +\begin{itemdescr} |
| 18491 | +\pnum |
| 18492 | +\mandates \tcode{S} is a complete type. |
| 18493 | + |
| 18494 | +\pnum |
| 18495 | +\returns \tcode{true} if and only if |
| 18496 | + \tcode{S} is a standard-layout type, |
| 18497 | + \tcode{M} is an object type, |
| 18498 | + \tcode{m} is not null, |
| 18499 | + and each object \tcode{s} of type \tcode{S} |
| 18500 | + is pointer-interconvertible\iref{basic.compound} |
| 18501 | + with its subobject \tcode{s.*m}. |
| 18502 | +\end{itemdescr} |
| 18503 | + |
| 18504 | +\indexlibrary{\idxcode{is_corresponding_member}} |
| 18505 | +\begin{itemdecl} |
| 18506 | +template<class S1, class S2, class M1, class M2> |
| 18507 | +constexpr bool |
| 18508 | +is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept; |
| 18509 | +\end{itemdecl} |
| 18510 | + |
| 18511 | +\begin{itemdescr} |
| 18512 | +\pnum |
| 18513 | +\mandates \tcode{S1} and \tcode{S2} are complete types. |
| 18514 | + |
| 18515 | +\pnum |
| 18516 | +\returns \tcode{true} if and only if |
| 18517 | + \tcode{S1} and \tcode{S2} are standard-layout types, |
| 18518 | + \tcode{M1} and \tcode{M2} are object types, |
| 18519 | + \tcode{m1} and \tcode{m2} are not null, |
| 18520 | + and \tcode{m1} and \tcode{m2} point to corresponding members of |
| 18521 | + the common initial sequence\iref{class.mem} of \tcode{S1} and \tcode{S2} |
| 18522 | +\end{itemdescr} |
| 18523 | + |
| 18524 | +\pnum |
| 18525 | +\begin{note} |
| 18526 | +The type of a pointer-to-member expression \tcode{\&C::b} |
| 18527 | +is not always a pointer to member of \tcode{C}, |
| 18528 | +leading to potentially surprising results |
| 18529 | +when using these functions in conjunction with inheritance. |
| 18530 | +Consider the following example: |
| 18531 | +\begin{codeblock} |
| 18532 | +struct A { int a; }; // a standard-layout class |
| 18533 | +struct B { int b; }; // a standard-layout class |
| 18534 | +struct C: public A, public B { }; // not a standard-layout class |
| 18535 | + |
| 18536 | +static_assert( is_pointer_interconvertible_with_class( &C::b ) ); |
| 18537 | + // Succeeds because, despite its appearance, \tcode{\&C::b} has type |
| 18538 | + // "pointer to member of \tcode{B} of type \tcode{int}". |
| 18539 | +static_assert( is_pointer_interconvertible_with_class<C>( &C::b ) ); |
| 18540 | + // Forces the use of class \tcode{C}, and fails. |
| 18541 | + |
| 18542 | +static_assert( is_corresponding_member( &C::a, &C::b ) ); |
| 18543 | + // Succeeds because, despite its appearance, \tcode{\&C::a} and \tcode{\&C::b} have types |
| 18544 | + // "pointer to member of \tcode{A} of type \tcode{int}" and |
| 18545 | + // "pointer to member of \tcode{B} of type \tcode{int}", respectively. |
| 18546 | +static_assert( is_corresponding_member<C, C>( &C::a, &C::b ) ); |
| 18547 | + // Forces the use of class \tcode{C}, and fails. |
| 18548 | +\end{codeblock} |
| 18549 | +\end{note} |
| 18550 | + |
18443 | 18551 | \rSec2[meta.endian]{Endian}
|
18444 | 18552 |
|
18445 | 18553 | \pnum
|
|
0 commit comments