22 Containers library [containers]

22.2 Container requirements [container.requirements]

22.2.4 Node handles [container.node]

22.2.4.1 Overview [container.node.overview]

A node handle is an object that accepts ownership of a single element from an associative container ([associative.reqmts]) or an unordered associative container ([unord.req]).
It may be used to transfer that ownership to another container with compatible nodes.
Containers with compatible nodes have the same node handle type.
Elements may be transferred in either direction between container types in the same row of Table 81.
Table 81: Container types with compatible nodes [tab:container.node.compat]
map<K, T, C1, A>
map<K, T, C2, A>
map<K, T, C1, A>
multimap<K, T, C2, A>
set<K, C1, A>
set<K, C2, A>
set<K, C1, A>
multiset<K, C2, A>
unordered_­map<K, T, H1, E1, A>
unordered_­map<K, T, H2, E2, A>
unordered_­map<K, T, H1, E1, A>
unordered_­multimap<K, T, H2, E2, A>
unordered_­set<K, H1, E1, A>
unordered_­set<K, H2, E2, A>
unordered_­set<K, H1, E1, A>
unordered_­multiset<K, H2, E2, A>
If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container when the element was extracted.
If a node handle is empty, it contains no allocator.
Class node-handle is for exposition only.
If a user-defined specialization of pair exists for pair<const Key, T> or pair<Key, T>, where Key is the container's key_­type and T is the container's mapped_­type, the behavior of operations involving node handles is undefined.
template<unspecified> class node-handle { public: // These type declarations are described in Tables 82 and 83. using value_type = see below; // not present for map containers using key_type = see below; // not present for set containers using mapped_type = see below; // not present for set containers using allocator_type = see below; private: using container_node_type = unspecified; // exposition only using ator_traits = allocator_traits<allocator_type>; // exposition only typename ator_traits::template rebind_traits<container_node_type>::pointer ptr_; // exposition only optional<allocator_type> alloc_; // exposition only public: // [container.node.cons], constructors, copy, and assignment constexpr node-handle() noexcept : ptr_(), alloc_() {} node-handle(node-handle&&) noexcept; node-handle& operator=(node-handle&&); // [container.node.dtor], destructor ~node-handle(); // [container.node.observers], observers value_type& value() const; // not present for map containers key_type& key() const; // not present for set containers mapped_type& mapped() const; // not present for set containers allocator_type get_allocator() const; explicit operator bool() const noexcept; [[nodiscard]] bool empty() const noexcept; // [container.node.modifiers], modifiers void swap(node-handle&) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value); friend void swap(node-handle& x, node-handle& y) noexcept(noexcept(x.swap(y))) { x.swap(y); } };

22.2.4.2 Constructors, copy, and assignment [container.node.cons]

node-handle(node-handle&& nh) noexcept;
Effects: Constructs a node-handle object initializing ptr_­ with nh.ptr_­.
Move constructs alloc_­ with nh.alloc_­.
Assigns nullptr to nh.ptr_­ and assigns nullopt to nh.alloc_­.
node-handle& operator=(node-handle&& nh);
Preconditions: Either !alloc_­, or ator_­traits​::​propagate_­on_­container_­move_­assignment​::​value is true, or alloc_­ == nh.alloc_­.
Effects:
  • If ptr_­ != nullptr, destroys the value_­type subobject in the container_­node_­type object pointed to by ptr_­ by calling ator_­traits​::​destroy, then deallocates ptr_­ by calling ator_­traits​::​template rebind_­traits<container_­node_­type>​::​deallocate.
  • Assigns nh.ptr_­ to ptr_­.
  • If !alloc_­ or ator_­traits​::​propagate_­on_­container_­move_­assignment​::​value is true,
    move assigns nh.alloc_­ to alloc_­.
  • Assigns nullptr to nh.ptr_­ and assigns nullopt to nh.alloc_­.
Returns: *this.
Throws: Nothing.

22.2.4.3 Destructor [container.node.dtor]

~node-handle();
Effects: If ptr_­ != nullptr, destroys the value_­type subobject in the container_­node_­type object pointed to by ptr_­ by calling ator_­traits​::​destroy, then deallocates ptr_­ by calling ator_­traits​::​template rebind_­traits<container_­node_­type>​::​deallocate.

22.2.4.4 Observers [container.node.observers]

value_type& value() const;
Preconditions: empty() == false.
Returns: A reference to the value_­type subobject in the container_­node_­type object pointed to by ptr_­.
Throws: Nothing.
key_type& key() const;
Preconditions: empty() == false.
Returns: A non-const reference to the key_­type member of the value_­type subobject in the container_­node_­type object pointed to by ptr_­.
Throws: Nothing.
Remarks: Modifying the key through the returned reference is permitted.
mapped_type& mapped() const;
Preconditions: empty() == false.
Returns: A reference to the mapped_­type member of the value_­type subobject in the container_­node_­type object pointed to by ptr_­.
Throws: Nothing.
allocator_type get_allocator() const;
Preconditions: empty() == false.
Returns: *alloc_­.
Throws: Nothing.
explicit operator bool() const noexcept;
Returns: ptr_­ != nullptr.
[[nodiscard]] bool empty() const noexcept;
Returns: ptr_­ == nullptr.

22.2.4.5 Modifiers [container.node.modifiers]

void swap(node-handle& nh) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value);
Preconditions: !alloc_­, or !nh.alloc_­, or ator_­traits​::​propagate_­on_­container_­swap​::​value is true, or alloc_­ == nh.alloc_­.
Effects: Calls swap(ptr_­, nh.ptr_­).
If !alloc_­, or !nh.alloc_­, or ator_­traits​::​propagate_­on_­container_­swap​::​value is true calls swap(alloc_­, nh.alloc_­).