0
  B   ˆl–Ü4ý(”†»â‚À¹q ©‹FÿÂ„Yh_†I|¥�+a–Ým_J*j"Tâ€rãMÜlJbÑ¿Æ ,L    // Node handles for containers -*- C++ -*-

// Copyright (C) 2016-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file bits/node_handle.h
 *  This is an internal header file, included by other library headers.
 *  Do not attempt to use it directly.
 *  @headername{map,set,unordered_map,unordered_set}
 */

#ifndef _NODE_HANDLE
#define _NODE_HANDLE 1

#pragma GCC system_header

#if __cplusplus >= 201703L
# define __cpp_lib_node_extract 201606

#include <new>
#include <bits/alloc_traits.h>
#include <bits/ptr_traits.h>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @defgroup node_handles Node handles
   * @ingroup associative_containers
   * @since C++17
   *
   * The associative containers (`map`, `set`, `multimap` and `multiset`)
   * support extracting and re-inserting nodes from the container. Those
   * operations use the container's `node_handle` type, which is an alias
   * for a `_Node_handle<...>` type. You should always use the container's
   * `node_handle` type (e.g. `std::set<int>::node_handle`) to refer to
   * these types, not the non-standard internal `_Node_handle` names.
   *
   * @{
   */

  /// Base class for node handle types of maps and sets.
  template<typename _Val, typename _NodeAlloc>
    class _Node_handle_common
    {
      using _AllocTraits = allocator_traits<_NodeAlloc>;

    public:
      using allocator_type = __alloc_rebind<_NodeAlloc, _Val>;

      allocator_type
      get_allocator() const noexcept
      {
	__glibcxx_assert(!this->empty());
	return allocator_type(_M_alloc._M_alloc);
      }

      explicit operator bool() const noexcept { return _M_ptr != nullptr; }

      [[nodiscard]] bool empty() const noexcept { return _M_ptr == nullptr; }

    /// @cond undocumented
    protected:
      constexpr _Node_handle_common() noexcept : _M_ptr() { }

      ~_Node_handle_common()
      {
	if (!empty())
	  _M_reset();
      }

      _Node_handle_common(_Node_handle_common&& __nh) noexcept
      : _M_ptr(__nh._M_ptr)
      {
	if (_M_ptr)
	  _M_move(std::move(__nh));
      }

      _Node_handle_common&
      operator=(_Node_handle_common&& __nh) noexcept
      {
	if (empty())
	  {
	    if (!__nh.empty())
	      _M_move(std::move(__nh));
	  }
	else if (__nh.empty())
	  _M_reset();
	else
	  {
	    // Free the current node before replacing the allocator.
	    _AllocTraits::destroy(*_M_alloc, _M_ptr->_M_valptr());
	    _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1);

	    _M_alloc = __nh._M_alloc.release(); // assigns if POCMA
	    _M_ptr = __nh._M_ptr;
	    __nh._M_ptr = nullptr;
	  }
	return *this;
      }

      _Node_handle_common(typename _AllocTraits::pointer __ptr,
			  const _NodeAlloc& __alloc)
      : _M_ptr(__ptr), _M_alloc(__alloc)
      {
	__glibcxx_assert(__ptr != nullptr);
      }

      void
      _M_swap(_Node_handle_common& __nh) noexcept
      {
	if (empty())
	  {
	    if (!__nh.empty())
	      _M_move(std::move(__nh));
	  }
	else if (__nh.empty())
	  __nh._M_move(std::move(*this));
	else
	  {
	   