std::is_poi...e_with_class(3)
π std::is_pointer_interconvertible_with_class β C++ Standard Library, bestie
Okay so this one is from the C++ Standard Library, queen of the <type_traits> header, and it's the compile-time trait that asks the big question: is this pointer-to-member thing actually sitting at the same address as the whole object? Let's get into it π
β¨ NAME β¨
std::is_pointer_interconvertible_with_class β and yeah, it's said twice in the original, so I'm saying it twice too: std::is_pointer_interconvertible_with_class. Iconic, repetitive, slay π
πΈ SYNOPSIS πΈ
Defined in header <type_traits>:
template< class S, class M >
constexpr bool is_pointer_interconvertible_with_class( M S::* mp )
- since: C++20
- noexcept: yes babe, it's
noexcept
So here's the vibe: given an object s of type S, this thing works out whether s.*mp refers to a subobject of s and whether s is pointer-interconvertible with its subobject s.*mp.
β οΈ Real talk though: the program is ill-formed if S is not a complete type. Not "returns false", not "warns you" β ill-formed. Periodt π
And also, listen carefully because this is the important bit: if S is not a StandardLayoutType, or M is not an object type, or mp is equal to nullptr, the result is always false. No surprises, no maybe, just false π«Ά
π¦ PARAMETERS π¦
mpβ a pointer-to-member to detect. That's the one and only thing you're handing it π
π RETURN VALUE π
It gives you true if s.*mp refers to a subobject of s and s is pointer-interconvertible with its subobject s.*mp. Otherwise you get false.
And where's s from? s is an object of type S. Keeping the receipts π
π NOTES π (the lore drop)
Okay, this part is lowkey the most important, so pay attention bestie π§ β¨
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. So the type can surprise you. That's exactly why you can specify the template arguments explicitly, to avoid potentially surprising results. Do it. Trust π
Then there's this beautiful little fact: if there is a value mp of type M S::* such that std::is_pointer_interconvertible_with_class(mp) == true, then reinterpret_cast<M&>(s) has a well-defined result and it refers to the same subobject as s.*mp, where s is a valid lvalue of type S. Well-defined. We love to see it π₯Ή
And on common platforms, the bit pattern of mp is all zero if std::is_pointer_interconvertible_with_class(mp) == true. Cute little implementation detail, iykyk π
π Feature-test macro
Here's the feature-test macro situation, and yes I'm keeping every cell:
- Macro:
__cpp_lib_is_pointer_interconvertible - Value:
201907L - Std: (C++20)
- Feature: Pointer-interconvertibility traits:
std::is_pointer_interconvertible_base_ofstd::is_pointer_interconvertible_with_class
π EXAMPLE π
// Run this code
#include <type_traits>
struct Foo { int x; };
struct Bar { int y; };
struct Baz : Foo, Bar {}; // not standard-layout
static_assert( not std::is_same_v<decltype(&Baz::x), int Baz::*> );
static_assert( std::is_pointer_interconvertible_with_class(&Baz::x) );
static_assert( not std::is_pointer_interconvertible_with_class<Baz, int>(&Baz::x) );
int main() { }
Look at those static_asserts go β the first one proving that decltype(&Baz::x) is not int Baz::* (told you it gets weird), the second one passing, and the third one failing once you spell out the template arguments. Chef's kiss π₯
π SEE ALSO π
is_standard_layout(C++11) β checks if a type is a standard-layout type (class template)is_member_object_pointer(C++11) β checks if a type is a pointer to a non-static member object (class template)
Anyway bestie, that's the whole page β sourced from http://cppreference.com, dated 2024.06.10, and filed under std::is_poi...e_with_class(3). Go be pointer-interconvertible with your subobjects, ily π«Άπβ¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms