std::is_cor...ding_member(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’– std::is_corresponding_member πŸ’–

okay so bestie, we're in the C++ Standard Library today, specifically the <type_traits> corner of it, and this one's a std::is_corresponding_member situation. it's giving "quiet little trait that goes feral in aggregate-initialization discourse," and honestly? i'm obsessed.


✨ Synopsis ✨

first things first, it lives in this header, periodt:

#include <type_traits>

and here's the signature, character for character, no cap:

template< class S1, class S2, class M1, class M2 >
constexpr bool is_corresponding_member( M1 S1::* mp, M2 S2::* mq )

so yes, it's constexpr and it's been around (since C++20) β€” and it's noexcept; too, she doesn't throw, she simply tells you the truth.

what does she do? πŸ’… she determines whether mp and mq refer to corresponding members in the common initial sequence of S1 and S2. like, are these two pointer-to-members pointing at the same slot in the shared layout prefix of those two types. that's the whole gig.

🫢 bestie heads up: the program is ill-formed if either S1 or S2 is an incomplete type. so don't be out here with incomplete types, that's not the vibe.

also, the boring-but-important escape hatch: if either S1 or S2 is not a StandardLayoutType, or either M1 or M2 is not an object type, or either mp or mq is equal to nullptr β€” the result is always false. always. no exceptions. it doesn't get mad, it just says no. 😭


🌸 Parameters 🌸

  • mp, mq β€” pointers-to-member to detect. that's it, those are the two besties under inspection πŸ”

πŸŽ€ Return value πŸŽ€

true if mp and mq refer to corresponding members in the common initial sequence of S1 and S2 β€” otherwise false. simple. iconic. slay.


πŸ¦‹ Notes πŸ¦‹

okay this part is genuinely the tea, so pay attention πŸ“:

the type of a pointer-to-member expression &S::m is not always M S::*, where m is of type M, because m may be a member inherited from a base class of S. sneaky little inheritance moment. πŸ™ˆ

so the template arguments can be specified explicitly in order to avoid potentially surprising results. iykyk β€” sometimes you gotta spell it out.


πŸ”₯ Example πŸ”₯

run this code, bestie, it speaks for itself:

// Run this code

#include <type_traits>

struct Foo
{
    int x;
    double d;
};

struct Bar
{
    int y;
    double z;
};

struct Baz : Foo, Bar {}; // not standard-layout

static_assert(
    std::is_same_v<decltype(&Baz::x), int Foo::*> == true &&
    std::is_same_v<decltype(&Baz::y), int Bar::*> == true &&
    std::is_corresponding_member(&Foo::x, &Bar::y) == true &&
    std::is_corresponding_member(&Foo::d, &Bar::z) == true &&
    std::is_corresponding_member(&Baz::x, &Baz::y) == true &&
    std::is_corresponding_member<Baz, Baz, int, int>(&Baz::x, &Baz::y)
       == false
);

int main() {}

look at that last line. πŸ‘‘ std::is_corresponding_member<Baz, Baz, int, int>(&Baz::x, &Baz::y) is false when you spell the template args out β€” and the default dedecution version above it was true. that's literally the whole Notes section living its best life in real time. main character energy, fr fr.


πŸ’œ See also πŸ’œ

  • is_standard_layout (C++11) β€” checks if a type is a standard-layout type (class template) ✨
  • is_layout_compatible (C++20) β€” checks if two types are layout-compatible (class template) πŸ’«
  • is_member_object_pointer (C++11) β€” checks if a type is a pointer to a non-static member object (class template) ⭐

aaaand that's the page, bestie! 🧚 source/version and date check, so you know this roundup is legit: it's from cppreference.com, version 2024.06.10, and your girl std::is_corresponding_member(3) says goodnight. go forth and check your common initial sequences responsibly. πŸ’–πŸŒˆ

πŸ“¦ where this page comes from