20 Memory management library [mem]

20.3 Pointer tagging [ptrtag]

20.3.2 Class template pointer_tag_pair [ptrtag.pair]


20.3.2.1 General [ptrtag.pair.general]

20.3.2.2 Constructors [ptrtag.pair.cons]

20.3.2.3 Support for overaligned pointers [ptrtag.pair.overalign]

20.3.2.4 Tagged pointer operations [ptrtag.pair.tagops]

20.3.2.5 Accessors [ptrtag.pair.accessors]

20.3.2.6 Swap [ptrtag.pair.swap]

20.3.2.7 Comparisons [ptrtag.pair.comp]

20.3.2.8 Tuple interface [ptrtag.pair.get]


20.3.2.1 General [ptrtag.pair.general]

The class template pointer_tag_pair provides a type to store an object pointer together with a tag value.
namespace std { template<class U, class PtrT, unsigned BitsRequested, size_t Alignment = alignof(U)> concept tagging-compatible-pointee = // exposition only convertible_to<U*, PtrT> && pointer_bits_available(Alignment) >= BitsRequested && (is_void_v<element-of<PtrT>> || is_scalar_v<element-of<PtrT>> || is_union_v<element-of<PtrT>> || is_pointer_interconvertible_base_of_v<element-of<PtrT>, U>); template<class TagT> constexpr unsigned tag-bit-width(TagT value) noexcept; // exposition only template<class Ptr, unsigned BitsRequested = bits-available<element-of<Ptr>>, class TagT = unsigned> class pointer_tag_pair { // freestanding public: using pointer_type = Ptr; using element_type = pointer_traits<Ptr>::element_type; using tagged_pointer_type = see below; using tag_type = TagT; static constexpr unsigned bits_requested = BitsRequested; // [ptrtag.pair.cons], constructors constexpr pointer_tag_pair() noexcept; template<tagging-compatible-pointee<pointer_type, bits_requested> U> constexpr pointer_tag_pair(U* p, tag_type t); constexpr pointer_tag_pair(nullptr_t p, tag_type t); // [ptrtag.pair.overalign], support for overaligned pointers template<size_t PromisedAlignment, tagging-compatible-pointee<pointer_type, bits_requested, PromisedAlignment> U> static constexpr pointer_tag_pair from_overaligned(U* p, tag_type t); // [ptrtag.pair.tagops], tagged pointer operations tagged_pointer_type tagged_pointer() const noexcept; static pointer_tag_pair from_tagged(tagged_pointer_type p) noexcept; // [ptrtag.pair.accessors], accessors constexpr pointer_type pointer() const noexcept; constexpr tag_type tag() const noexcept; // [ptrtag.pair.swap], swap constexpr void swap(pointer_tag_pair& o) noexcept; // [ptrtag.pair.comp], comparisons friend constexpr see below operator<=>(pointer_tag_pair lhs, pointer_tag_pair rhs) noexcept requires three_way_comparable<tag_type>; friend constexpr bool operator==(pointer_tag_pair, pointer_tag_pair) noexcept requires equality_comparable<tag_type>; }; template<class Ptr> pointer_tag_pair(Ptr*) -> pointer_tag_pair<Ptr*>; template<class Ptr, class TagT> pointer_tag_pair(Ptr*, TagT tag) -> pointer_tag_pair<Ptr*, bits-available<element-of<Ptr>>, TagT>; }
An object of class pointer_tag_pair<Ptr, BitsRequested, TagT> represents a pair of pointer value of type Ptr and tag value of type TagT.
Each specialization PT of pointer_tag_pair is a trivially copyable type that models copyable such that sizeof(PT) is equal to sizeof(Ptr) and alignof(PT) is equal to alignof(Ptr).
Mandates:
  • is_same_v<remove_cvref_t<Ptr>, Ptr> is true.
  • is_same_v<remove_cvref_t<TagT>, TagT> is true.
  • is_pointer_v<Ptr> && !is_function_v<remove_pointer_t<Ptr>> is true.
  • is_unsigned_v<UT> is true, where UT is underlying_type_t<TagT> if TagT is an enumeration type, and TagT otherwise.
  • sizeof(TagT) <= sizeof(void*) is true.
  • BitsRequested <= max_pointer_bits_available is true.
template<class T> constexpr unsigned tag-bit-width(T v) noexcept;
Returns: static_cast<unsigned>(bit_width(to_underlying(v))) if is_enum_v<T> is true, otherwise static_cast<unsigned>(bit_width(v)).

20.3.2.2 Constructors [ptrtag.pair.cons]

constexpr pointer_tag_pair() noexcept;
Postconditions: pointer() is equal to nullptr and tag() is equal to TagT().
template<tagging-compatible-pointee<pointer_type, bits_requested> U> constexpr pointer_tag_pair(U* p, tag_type t); constexpr pointer_tag_pair(nullptr_t p, tag_type t);
Constant When: Preconditions are met.
Preconditions:
Postconditions: pointer() is equal to p and tag() is equal to t.
Throws: Nothing.

20.3.2.3 Support for overaligned pointers [ptrtag.pair.overalign]

template<size_t PromisedAlignment, tagging-compatible-pointee<pointer_type, bits_requested, PromisedAlignment> U> static constexpr pointer_tag_pair from_overaligned(U* p, tag_type t);
Constant When: Preconditions are met.
Preconditions:
  • p is not a pointer past the end of an object ([basic.compound]).
  • p == nullptr || is_sufficiently_aligned<PromisedAlignment>(p) is true.
  • tag-bit-width(t) <= bits_requested is true.
Returns: An object ptp of type pointer_tag_pair such that both ptp.pointer() is equal to p and ptp.tag() is equal to t.
Throws: Nothing.

20.3.2.4 Tagged pointer operations [ptrtag.pair.tagops]

using tagged_pointer_type = see below;
tagged_pointer_type denotes cv void*, for cv such that pointer denotes cv U* for some type U.
tagged_pointer_type tagged_pointer() const noexcept;
Returns: An unspecified value tp of tagged_pointer_type type such that for any specialization DP of pointer_tag_pair and alignment value A for which
  • pointer_bits_available(A) >= DP​::​bits_requested is true,
  • is_sufficiently_aligned<A>(ptr) is true, and
  • tag-bit-width(tag) <= DP​::​bits_requested is true,
DP​::​from_tagged(tp) produces an object dp such that reinterpret_cast<pointer_type>(dp.pointer()) is equal to ptr and static_cast<TagT>(dp.tag()) is equal to tag.
[Note 1: 
This function returns an invalid pointer value ([basic.compound]) with implementation-defined behavior.
— end note]
static pointer_tag_pair from_tagged(tagged_pointer_type p) noexcept;
Returns: An object dp of type pointer_tag_type, such that
  • reinterpret_cast<pointer_type>(sp.pointer()) is equal to dp.pointer() and
    static_cast<TagT>(sp.tag()) is equal to dp.tag(), if p is equal to sp.tagged_pointer() for some object sp of a type that is a specialization of pointer_tag_type, such that for some alignment value A
    • pointer_bits_available(A) >= bits_requested is true,
    • is_sufficiently_aligned<A>(sp.pointer()) is true, and
    • tag-bit-width(sp.tag()) <= bits_requested is true,
  • otherwise, the values of dp.pointer() and dp.tag() are unspecified.

20.3.2.5 Accessors [ptrtag.pair.accessors]

constexpr pointer_type pointer() const noexcept;
Returns: The pointer value represented by *this.
constexpr tag_type tag() const noexcept;
Returns: The tag value represented by *this.

20.3.2.6 Swap [ptrtag.pair.swap]

constexpr void swap(pointer_tag_pair& o) noexcept;
Effects: Exchanges the values of *this and o.

20.3.2.7 Comparisons [ptrtag.pair.comp]

friend constexpr auto operator<=>(pointer_tag_pair lhs, pointer_tag_pair rhs) noexcept requires three_way_comparable<tag_type>;
Effects: Equivalent to: return pair(lhs.pointer(), lhs.tag()) <=> pair(rhs.pointer(), rhs.tag());
Recommended practice: Directly compare the internal bit representations if the expression lhs.tag() <=> rhs.tag() results in a call to a built-in operator <=> comparing values of type tag_type.
[Note 1: 
The result of comparing unrelated pointers is unspecified.
— end note]
friend constexpr bool operator==(pointer_tag_pair lhs, pointer_tag_pair rhs) noexcept requires equality_comparable<tag_type>;
Effects: Equivalent to: return pair(lhs.pointer(), lhs.tag()) == pair(rhs.pointer(), rhs.tag());
Recommended practice: Directly compare the internal bit representations if the expression lhs.tag() == rhs.tag() results in a call to a built-in operator == comparing values of type tag_type.

20.3.2.8 Tuple interface [ptrtag.pair.get]

template<class Ptr, unsigned BitsRequested, class TagT> constexpr tuple_element_t<I, pointer_tag_pair<Ptr, BitsRequested, TagT>> get(pointer_tag_pair<Ptr, BitsRequested, TagT> p) noexcept;
Mandates: I < 2.
Returns:
  • p.pointer() if I is equal to zero,
  • p.tag() otherwise.