// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
#define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_

#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/container/internal/btree.h"  // IWYU pragma: export
#include "absl/container/internal/common.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {

// A common base class for btree_set, btree_map, btree_multiset, and
// btree_multimap.
template <typename Tree>
class btree_container {
  using params_type = typename Tree::params_type;

 protected:
  // Alias used for heterogeneous lookup functions.
  // `key_arg<K>` evaluates to `K` when the functors are transparent and to
  // `key_type` otherwise. It permits template argument deduction on `K` for the
  // transparent case.
  template <class K>
  using key_arg =
      typename KeyArg<params_type::kIsKeyCompareTransparent>::template type<
          K, typename Tree::key_type>;

 public:
  using key_type = typename Tree::key_type;
  using value_type = typename Tree::value_type;
  using size_type = typename Tree::size_type;
  using difference_type = typename Tree::difference_type;
  using key_compare = typename Tree::original_key_compare;
  using value_compare = typename Tree::value_compare;
  using allocator_type = typename Tree::allocator_type;
  using reference = typename Tree::reference;
  using const_reference = typename Tree::const_reference;
  using pointer = typename Tree::pointer;
  using const_pointer = typename Tree::const_pointer;
  using iterator = typename Tree::iterator;
  using const_iterator = typename Tree::const_iterator;
  using reverse_iterator = typename Tree::reverse_iterator;
  using const_reverse_iterator = typename Tree::const_reverse_iterator;
  using node_type = typename Tree::node_handle_type;

  // Constructors/assignments.
  btree_container() : tree_(key_compare(), allocator_type()) {}
  explicit btree_container(const key_compare &comp,
                           const allocator_type &alloc = allocator_type())
      : tree_(comp, alloc) {}
  explicit btree_container(const allocator_type &alloc)
      : tree_(key_compare(), alloc) {}

  btree_container(const btree_container &other)
      : btree_container(other, absl::allocator_traits<allocator_type>::
                                   select_on_container_copy_construction(
                                       other.get_allocator())) {}
  btree_container(const btree_container &other, const allocator_type &alloc)
      : tree_(other.tree_, alloc) {}

  btree_container(btree_container &&other) noexcept(
      std::is_nothrow_move_constructible<Tree>::value) = default;
  btree_container(btree_container &&other, const allocator_type &alloc)
      : tree_(std::move(other.tree_), alloc) {}

  btree_container &operator=(const btree_container &other) = default;
  btree_container &operator=(btree_container &&other) noexcept(
      std::is_nothrow_move_assignable<Tree>::value) = default;

  // Iterator routines.
  iterator begin() { return tree_.begin(); }
  const_iterator begin() const { return tree_.begin(); }
  const_iterator cbegin() const { return tree_.begin(); }
  iterator end() { return tree_.end(); }
  const_iterator end() const { return tree_.end(); }
  const_iterator cend() const { return tree_.end(); }
  reverse_iterator rbegin() { return tree_.rbegin(); }
  const_reverse_iterator rbegin() const { return tree_.rbegin(); }
  const_reverse_iterator crbegin() const { return tree_.rbegin(); }
  reverse_iterator rend() { return tree_.rend(); }
  const_reverse_iterator rend() const { return tree_.rend(); }
  const_reverse_iterator crend() const { return tree_.rend(); }

  // Lookup routines.
  template <typename K = key_type>
  size_type count(const key_arg<K> &key) const {
    auto equal_range = this->equal_range(key);
    return std::distance(equal_range.first, equal_range.second);
  }
  template <typename K = key_type>
  iterator find(const key_arg<K> &key) {
    return tree_.find(key);
  }
  template <typename K = key_type>
  const_iterator find(const key_arg<K> &key) const {
    return tree_.find(key);
  }
  template <typename K = key_type>
  bool contains(const key_arg<K> &key) const {
    return find(key) != end();
  }
  template <typename K = key_type>
  iterator lower_bound(const key_arg<K> &key) {
    return tree_.lower_bound(key);
  }
  template <typename K = key_type>
  const_iterator lower_bound(const key_arg<K> &key) const {
    return tree_.lower_bound(key);
  }
  template <typename K = key_type>
  iterator upper_bound(const key_arg<K> &key) {
    return tree_.upper_bound(key);
  }
  template <typename K = key_type>
  const_iterator upper_bound(const key_arg<K> &key) const {
    return tree_.upper_bound(key);
  }
  template <typename K = key_type>
  std::pair<iterator, iterator> equal_range(const key_arg<K> &key) {
    return tree_.equal_range(key);
  }
  template <typename K = key_type>
  std::pair<const_iterator, const_iterator> equal_range(
      const key_arg<K> &key) const {
    return tree_.equal_range(key);
  }

  // Deletion routines. Note that there is also a deletion routine that is
  // specific to btree_set_container/btree_multiset_container.

  // Erase the specified iterator from the btree. The iterator must be valid
  // (i.e. not equal to end()).  Return an iterator pointing to the node after
  // the one that was erased (or end() if none exists).
  iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); }
  iterator erase(iterator iter) { return tree_.erase(iter); }
  iterator erase(const_iterator first, const_iterator last) {
    return tree_.erase_range(iterator(first), iterator(last)).second;
  }
  template <typename K = key_type>
  size_type erase(const key_arg<K> &key) {
    auto equal_range = this->equal_range(key);
    return tree_.erase_range(equal_range.first, equal_range.second).first;
  }

  // Extract routines.
  node_type extract(iterator position) {
    // Use Construct instead of Transfer because the rebalancing code will
    // destroy the slot later.
    auto node =
        CommonAccess::Construct<node_type>(get_allocator(), position.slot());
    erase(position);
    return node;
  }
  node_type extract(const_iterator position) {
    return extract(iterator(position));
  }

  // Utility routines.
  ABSL_ATTRIBUTE_REINITIALIZES void clear() { tree_.clear(); }
  void swap(btree_container &other) { tree_.swap(other.tree_); }
  void verify() const { tree_.verify(); }

  // Size routines.
  size_type size() const { return tree_.size(); }
  size_type max_size() const { return tree_.max_size(); }
  bool empty() const { return tree_.empty(); }

  friend bool operator==(const btree_container &x, const btree_container &y) {
    if (x.size() != y.size()) return false;
    return std::equal(x.begin(), x.end(), y.begin());
  }

  friend bool operator!=(const btree_container &x, const btree_container &y) {
    return !(x == y);
  }

  friend bool operator<(const btree_container &x, const btree_container &y) {
    return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
  }

  friend bool operator>(const btree_container &x, const btree_container &y) {
    return y < x;
  }

  friend bool operator<=(const btree_container &x, const btree_container &y) {
    return !(y < x);
  }

  friend bool operator>=(const btree_container &x, const btree_container &y) {
    return !(x < y);
  }

  // The allocator used by the btree.
  allocator_type get_allocator() const { return tree_.get_allocator(); }

  // The key comparator used by the btree.
  key_compare key_comp() const { return key_compare(tree_.key_comp()); }
  value_compare value_comp() const { return tree_.value_comp(); }

  // Support absl::Hash.
  template <typename State>
  friend State AbslHashValue(State h, const btree_container &b) {
    for (const auto &v : b) {
      h = State::combine(std::move(h), v);
    }
    return State::combine(std::move(h), b.size());
  }

 protected:
  friend struct btree_access;
  Tree tree_;
};

// A common base class for btree_set and btree_map.
template <typename Tree>
class btree_set_container : public btree_container<Tree> {
  using super_type = btree_container<Tree>;
  using params_type = typename Tree::params_type;
  using init_type = typename params_type::init_type;
  using is_key_compare_to = typename params_type::is_key_compare_to;
  friend class BtreeNodePeer;

 protected:
  template <class K>
  using key_arg = typename super_type::template key_arg<K>;

 public:
  using key_type = typename Tree::key_type;
  using value_type = typename Tree::value_type;
  using size_type = typename Tree::size_type;
  using key_compare = typename Tree::original_key_compare;
  using allocator_type = typename Tree::allocator_type;
  using iterator = typename Tree::iterator;
  using const_iterator = typename Tree::const_iterator;
  using node_type = typename super_type::node_type;
  using insert_return_type = InsertReturnType<iterator, node_type>;

  // Inherit constructors.
  using super_type::super_type;
  btree_set_container() {}

  // Range constructors.
  template <class InputIterator>
  btree_set_container(InputIterator b, InputIterator e,
                      const key_compare &comp = key_compare(),
                      const allocator_type &alloc = allocator_type())
      : super_type(comp, alloc) {
    insert(b, e);
  }
  template <class InputIterator>
  btree_set_container(InputIterator b, InputIterator e,
                      const allocator_type &alloc)
      : btree_set_container(b, e, key_compare(), alloc) {}

  // Initializer list constructors.
  btree_set_container(std::initializer_list<init_type> init,
                      const key_compare &comp = key_compare(),
                      const allocator_type &alloc = allocator_type())
      : btree_set_container(init.begin(), init.end(), comp, alloc) {}
  btree_set_container(std::initializer_list<init_type> init,
                      const allocator_type &alloc)
      : btree_set_container(init.begin(), init.end(), alloc) {}

  // Insertion routines.
  std::pair<iterator, bool> insert(const value_type &v) {
    return this->tree_.insert_unique(params_type::key(v), v);
  }
  std::pair<iterator, bool> insert(value_type &&v) {
    return this->tree_.insert_unique(params_type::key(v), std::move(v));
  }
  template <typename... Args>
  std::pair<iterator, bool> emplace(Args &&... args) {
    // Use a node handle to manage a temp slot.
    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
                                                   std::forward<Args>(args)...);
    auto *slot = CommonAccess::GetSlot(node);
    return this->tree_.insert_unique(params_type::key(slot), slot);
  }
  iterator insert(const_iterator hint, const value_type &v) {
    return this->tree_
        .insert_hint_unique(iterator(hint), params_type::key(v), v)
        .first;
  }
  iterator insert(const_iterator hint, value_type &&v) {
    return this->tree_
        .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
        .first;
  }
  template <typename... Args>
  iterator emplace_hint(const_iterator hint, Args &&... args) {
    // Use a node handle to manage a temp slot.
    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
                                                   std::forward<Args>(args)...);
    auto *slot = CommonAccess::GetSlot(node);
    return this->tree_
        .insert_hint_unique(iterator(hint), params_type::key(slot), slot)
        .first;
  }
  template <typename InputIterator>
  void insert(InputIterator b, InputIterator e) {
    this->tree_.insert_iterator_unique(b, e, 0);
  }
  void insert(std::initializer_list<init_type> init) {
    this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
  }
  insert_return_type insert(node_type &&node) {
    if (!node) return {this->end(), false, node_type()};
    std::pair<iterator, bool> res =
        this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
                                  CommonAccess::GetSlot(node));
    if (res.second) {
      CommonAccess::Destroy(&node);
      return {res.first, true, node_type()};
    } else {
      return {res.first, false, std::move(node)};
    }
  }
  iterator insert(const_iterator hint, node_type &&node) {
    if (!node) return this->end();
    std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
        iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
        CommonAccess::GetSlot(node));
    if (res.second) CommonAccess::Destroy(&node);
    return res.first;
  }

  // Node extraction routines.
  template <typename K = key_type>
  node_type extract(const key_arg<K> &key) {
    const std::pair<iterator, bool> lower_and_equal =
        this->tree_.lower_bound_equal(key);
    return lower_and_equal.second ? extract(lower_and_equal.first)
                                  : node_type();
  }
  using super_type::extract;

  // Merge routines.
  // Moves elements from `src` into `this`. If the element already exists in
  // `this`, it is left unmodified in `src`.
  template <
      typename T,
      typename absl::enable_if_t<
          absl::conjunction<
              std::is_same<value_type, typename T::value_type>,
              std::is_same<allocator_type, typename T::allocator_type>,
              std::is_same<typename params_type::is_map_container,
                           typename T::params_type::is_map_container>>::value,
          int> = 0>
  void merge(btree_container<T> &src) {  // NOLINT
    for (auto src_it = src.begin(); src_it != src.end();) {
      if (insert(std::move(params_type::element(src_it.slot()))).second) {
        src_it = src.erase(src_it);
      } else {
        ++src_it;
      }
    }
  }

  template <
      typename T,
      typename absl::enable_if_t<
          absl::conjunction<
              std::is_same<value_type, typename T::value_type>,
              std::is_same<allocator_type, typename T::allocator_type>,
              std::is_same<typename params_type::is_map_container,
                           typename T::params_type::is_map_container>>::value,
          int> = 0>
  void merge(btree_container<T> &&src) {
    merge(src);
  }
};

// Base class for btree_map.
template <typename Tree>
class btree_map_container : public btree_set_container<Tree> {
  using super_type = btree_set_container<Tree>;
  using params_type = typename Tree::params_type;
  friend class BtreeNodePeer;

 private:
  template <class K>
  using key_arg = typename super_type::template key_arg<K>;

 public:
  using key_type = typename Tree::key_type;
  using mapped_type = typename params_type::mapped_type;
  using value_type = typename Tree::value_type;
  using key_compare = typename Tree::original_key_compare;
  using allocator_type = typename Tree::allocator_type;
  using iterator = typename Tree::iterator;
  using const_iterator = typename Tree::const_iterator;

  // Inherit constructors.
  using super_type::super_type;
  btree_map_container() {}

  // Insertion routines.
  // Note: the nullptr template arguments and extra `const M&` overloads allow
  // for supporting bitfield arguments.
  template <typename K = key_type, class M>
  std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k,
                                             const M &obj) {
    return insert_or_assign_impl(k, obj);
  }
  template <typename K = key_type, class M, K * = nullptr>
  std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj) {
    return insert_or_assign_impl(std::forward<K>(k), obj);
  }
  template <typename K = key_type, class M, M * = nullptr>
  std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj) {
    return insert_or_assign_impl(k, std::forward<M>(obj));
  }
  template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
  std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj) {
    return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
  }
  template <typename K = key_type, class M>
  iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
                            const M &obj) {
    return insert_or_assign_hint_impl(hint, k, obj);
  }
  template <typename K = key_type, class M, K * = nullptr>
  iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, const M &obj) {
    return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
  }
  template <typename K = key_type, class M, M * = nullptr>
  iterator insert_or_assign(const_iterator hint, const key_arg<K> &k, M &&obj) {
    return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
  }
  template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
  iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, M &&obj) {
    return insert_or_assign_hint_impl(hint, std::forward<K>(k),
                                      std::forward<M>(obj));
  }

  template <typename K = key_type, typename... Args,
            typename absl::enable_if_t<
                !std::is_convertible<K, const_iterator>::value, int> = 0>
  std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&... args) {
    return try_emplace_impl(k, std::forward<Args>(args)...);
  }
  template <typename K = key_type, typename... Args,
            typename absl::enable_if_t<
                !std::is_convertible<K, const_iterator>::value, int> = 0>
  std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&... args) {
    return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
  }
  template <typename K = key_type, typename... Args>
  iterator try_emplace(const_iterator hint, const key_arg<K> &k,
                       Args &&... args) {
    return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
  }
  template <typename K = key_type, typename... Args>
  iterator try_emplace(const_iterator hint, key_arg<K> &&k, Args &&... args) {
    return try_emplace_hint_impl(hint, std::forward<K>(k),
                                 std::forward<Args>(args)...);
  }

  template <typename K = key_type>
  mapped_type &operator[](const key_arg<K> &k) {
    return try_emplace(k).first->second;
  }
  template <typename K = key_type>
  mapped_type &operator[](key_arg<K> &&k) {
    return try_emplace(std::forward<K>(k)).first->second;
  }

  template <typename K = key_type>
  mapped_type &at(const key_arg<K> &key) {
    auto it = this->find(key);
    if (it == this->end())
      base_internal::ThrowStdOutOfRange("absl::btree_map::at");
    return it->second;
  }
  template <typename K = key_type>
  const mapped_type &at(const key_arg<K> &key) const {
    auto it = this->find(key);
    if (it == this->end())
      base_internal::ThrowStdOutOfRange("absl::btree_map::at");
    return it->second;
  }

 private:
  // Note: when we call `std::forward<M>(obj)` twice, it's safe because
  // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when
  // `ret.second` is false.
  template <class K, class M>
  std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {
    const std::pair<iterator, bool> ret =
        this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));
    if (!ret.second) ret.first->second = std::forward<M>(obj);
    return ret;
  }
  template <class K, class M>
  iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {
    const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
        iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));
    if (!ret.second) ret.first->second = std::forward<M>(obj);
    return ret.first;
  }

  template <class K, class... Args>
  std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {
    return this->tree_.insert_unique(
        k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),
        std::forward_as_tuple(std::forward<Args>(args)...));
  }
  template <class K, class... Args>
  iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {
    return this->tree_
        .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
                            std::forward_as_tuple(std::forward<K>(k)),
                            std::forward_as_tuple(std::forward<Args>(args)...))
        .first;
  }
};

// A common base class for btree_multiset and btree_multimap.
template <typename Tree>
class btree_multiset_container : public btree_container<Tree> {
  using super_type = btree_container<Tree>;
  using params_type = typename Tree::params_type;
  using init_type = typename params_type::init_type;
  using is_key_compare_to = typename params_type::is_key_compare_to;
  friend class BtreeNodePeer;

  template <class K>
  using key_arg = typename super_type::template key_arg<K>;

 public:
  using key_type = typename Tree::key_type;
  using value_type = typename Tree::value_type;
  using size_type = typename Tree::size_type;
  using key_compare = typename Tree::original_key_compare;
  using allocator_type = typename Tree::allocator_type;
  using iterator = typename Tree::iterator;
  using const_iterator = typename Tree::const_iterator;
  using node_type = typename super_type::node_type;

  // Inherit constructors.
  using super_type::super_type;
  btree_multiset_container() {}

  // Range constructors.
  template <class InputIterator>
  btree_multiset_container(InputIterator b, InputIterator e,
                           const key_compare &comp = key_compare(),
                           const allocator_type &alloc = allocator_type())
      : super_type(comp, alloc) {
    insert(b, e);
  }
  template <class InputIterator>
  btree_multiset_container(InputIterator b, InputIterator e,
                           const allocator_type &alloc)
      : btree_multiset_container(b, e, key_compare(), alloc) {}

  // Initializer list constructors.
  btree_multiset_container(std::initializer_list<init_type> init,
                           const key_compare &comp = key_compare(),
                           const allocator_type &alloc = allocator_type())
      : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
  btree_multiset_container(std::initializer_list<init_type> init,
                           const allocator_type &alloc)
      : btree_multiset_container(init.begin(), init.end(), alloc) {}

  // Insertion routines.
  iterator insert(const value_type &v) { return this->tree_.insert_multi(v); }
  iterator insert(value_type &&v) {
    return this->tree_.insert_multi(std::move(v));
  }
  iterator insert(const_iterator hint, const value_type &v) {
    return this->tree_.insert_hint_multi(iterator(hint), v);
  }
  iterator insert(const_iterator hint, value_type &&v) {
    return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
  }
  template <typename InputIterator>
  void insert(InputIterator b, InputIterator e) {
    this->tree_.insert_iterator_multi(b, e);
  }
  void insert(std::initializer_list<init_type> init) {
    this->tree_.insert_iterator_multi(init.begin(), init.end());
  }
  template <typename... Args>
  iterator emplace(Args &&... args) {
    // Use a node handle to manage a temp slot.
    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
                                                   std::forward<Args>(args)...);
    return this->tree_.insert_multi(CommonAccess::GetSlot(node));
  }
  template <typename... Args>
  iterator emplace_hint(const_iterator hint, Args &&... args) {
    // Use a node handle to manage a temp slot.
    auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
                                                   std::forward<Args>(args)...);
    return this->tree_.insert_hint_multi(iterator(hint),
                                         CommonAccess::GetSlot(node));
  }
  iterator insert(node_type &&node) {
    if (!node) return this->end();
    iterator res =
        this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
                                 CommonAccess::GetSlot(node));
    CommonAccess::Destroy(&node);
    return res;
  }
  iterator insert(const_iterator hint, node_type &&node) {
    if (!node) return this->end();
    iterator res = this->tree_.insert_hint_multi(
        iterator(hint),
        std::move(params_type::element(CommonAccess::GetSlot(node))));
    CommonAccess::Destroy(&node);
    return res;
  }

  // Node extraction routines.
  template <typename K = key_type>
  node_type extract(const key_arg<K> &key) {
    const std::pair<iterator, bool> lower_and_equal =
        this->tree_.lower_bound_equal(key);
    return lower_and_equal.second ? extract(lower_and_equal.first)
                                  : node_type();
  }
  using super_type::extract;

  // Merge routines.
  // Moves all elements from `src` into `this`.
  template <
      typename T,
      typename absl::enable_if_t<
          absl::conjunction<
              std::is_same<value_type, typename T::value_type>,
              std::is_same<allocator_type, typename T::allocator_type>,
              std::is_same<typename params_type::is_map_container,
                           typename T::params_type::is_map_container>>::value,
          int> = 0>
  void merge(btree_container<T> &src) {  // NOLINT
    for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
      insert(std::move(params_type::element(src_it.slot())));
    }
    src.clear();
  }

  template <
      typename T,
      typename absl::enable_if_t<
          absl::conjunction<
              std::is_same<value_type, typename T::value_type>,
              std::is_same<allocator_type, typename T::allocator_type>,
              std::is_same<typename params_type::is_map_container,
                           typename T::params_type::is_map_container>>::value,
          int> = 0>
  void merge(btree_container<T> &&src) {
    merge(src);
  }
};

// A base class for btree_multimap.
template <typename Tree>
class btree_multimap_container : public btree_multiset_container<Tree> {
  using super_type = btree_multiset_container<Tree>;
  using params_type = typename Tree::params_type;
  friend class BtreeNodePeer;

 public:
  using mapped_type = typename params_type::mapped_type;

  // Inherit constructors.
  using super_type::super_type;
  btree_multimap_container() {}
};

}  // namespace container_internal
ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
