23 Containers library [containers]

23.2 Container requirements [container.requirements]

23.2.4 Node handles [container.node]

23.2.4.1 node_handle 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 [tab:containers.node.compat].

Table 89 — Container types with compatible nodes
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. An implementation is permitted to provide equivalent functionality without providing a class with this name.

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 [tab:containers.associative.requirements] and [tab:HashRequirements]
  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;
  using ator_traits         = allocator_traits<allocator_type>;
  typename ator_traits::rebind_traits<container_node_type>::pointer ptr_;
  optional<allocator_type> alloc_;

public:
  constexpr node_handle() noexcept : ptr_(), alloc_() {}
  ~node_handle();
  node_handle(node_handle&&) noexcept;
  node_handle& operator=(node_handle&&);
  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;
  bool empty() const noexcept;
  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); }
};

23.2.4.2 node_handle 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);

Requires: Either !alloc_, or ator_traits::propagate_on_container_move_assignment 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::rebind_traits<container_node_type>::deallocate. Assigns nh.ptr_ to ptr_. If !alloc_ or ator_traits::propagate_on_container_move_assignment is true, move assigns nh.alloc_ to alloc_. Assigns nullptr to nh.ptr_ and assigns nullopt to nh.alloc_.

Returns: *this.

Throws: Nothing.

23.2.4.3 node_handle 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::rebind_traits<container_node_type>::deallocate.

23.2.4.4 node_handle observers [container.node.observers]

value_type& value() const;

Requires: 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;

Requires: 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;

Requires: 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;

Requires: empty() == false.

Returns: *alloc_.

Throws: Nothing.

explicit operator bool() const noexcept;

Returns: ptr_ != nullptr.

bool empty() const noexcept;

Returns: ptr_ == nullptr.

23.2.4.5 node_handle modifiers [container.node.modifiers]

void swap(node_handle& nh) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value);

Requires: !alloc_, or !nh.alloc_, or ator_traits::propagate_on_container_swap is true, or alloc_ == nh.alloc_.

Effects: Calls swap(ptr_, nh.ptr_). If !alloc_, or !nh.alloc_, or ator_traits::propagate_on_container_swap is true calls swap(alloc_, nh.alloc_).