[meta.member]

# 21 Metaprogramming library [[meta]](./#meta)

## 21.3 Metaprogramming and type traits [[type.traits]](type.traits#meta.member)

### 21.3.11 Member relationships [meta.member]

[ð](#lib:is_pointer_interconvertible_with_class)

`template<class S, class M>
  constexpr bool is_pointer_interconvertible_with_class(M S::*m) noexcept;
`

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2744)

*Mandates*: S is a complete type[.](#1.sentence-1)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2748)

*Returns*: true if and only if S is a standard-layout type, M is an object type, m is not null,
 and each object s of type S is pointer-interconvertible ([[basic.compound]](basic.compound "6.9.4 Compound types"))
 with its subobject s.*m[.](#2.sentence-1)

[ð](#lib:is_corresponding_member)

`template<class S1, class S2, class M1, class M2>
  constexpr bool is_corresponding_member(M1 S1::*m1, M2 S2::*m2) noexcept;
`

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2766)

*Mandates*: S1 and S2 are complete types[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2770)

*Returns*: true if and only if S1 and S2 are standard-layout struct ([[class.prop]](class.prop "11.2 Properties of classes")) types, M1 and M2 are object types, m1 and m2 are not null,
 and m1 and m2 point to corresponding members of
 the common initial sequence ([[class.mem]](class.mem "11.4 Class members")) of S1 and S2[.](#4.sentence-1)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L2780)

[*Note [1](#note-1)*:

The type of a pointer-to-member expression &C​::​b is not always a pointer to member of C,
leading to potentially surprising results
when using these functions in conjunction with inheritance[.](#5.sentence-1)

[*Example [1](#example-1)*: struct A { int a; }; // a standard-layout classstruct B { int b; }; // a standard-layout classstruct C: public A, public B { }; // not a standard-layout classstatic_assert( is_pointer_interconvertible_with_class( &C::b ) ); // Succeeds because, despite its appearance, &C​::​b has type// âpointer to member of B of type int''.static_assert( is_pointer_interconvertible_with_class<C>( &C::b ) ); // Forces the use of class C, and fails.static_assert( is_corresponding_member( &C::a, &C::b ) ); // Succeeds because, despite its appearance, &C​::​a and &C​::​b have types// âpointer to member of A of type int'' and// âpointer to member of B of type int'', respectively.static_assert( is_corresponding_member<C, C>( &C::a, &C::b ) ); // Forces the use of class C, and fails. â *end example*]

â *end note*]
