// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/utils/common.h" #include "td/utils/HashTableUtils.h" #include #include #include namespace td { template struct MapNode { using first_type = KeyT; using second_type = ValueT; using public_key_type = KeyT; using public_type = MapNode; KeyT first{}; union { ValueT second; }; const KeyT &key() const { return first; } MapNode &get_public() { return *this; } const MapNode &get_public() const { return *this; } MapNode() { } MapNode(KeyT key, ValueT value) : first(std::move(key)) { new (&second) ValueT(std::move(value)); DCHECK(!empty()); } MapNode(const MapNode &other) = delete; MapNode &operator=(const MapNode &other) = delete; MapNode(MapNode &&other) noexcept { *this = std::move(other); } void operator=(MapNode &&other) noexcept { DCHECK(empty()); DCHECK(!other.empty()); first = std::move(other.first); other.first = KeyT{}; new (&second) ValueT(std::move(other.second)); other.second.~ValueT(); } ~MapNode() { if (!empty()) { second.~ValueT(); } } void copy_from(const MapNode &other) { DCHECK(empty()); DCHECK(!other.empty()); first = other.first; new (&second) ValueT(other.second); } bool empty() const { return is_hash_table_key_empty(first); } void clear() { DCHECK(!empty()); first = KeyT(); second.~ValueT(); DCHECK(empty()); } template void emplace(KeyT key, ArgsT &&...args) { DCHECK(empty()); first = std::move(key); new (&second) ValueT(std::forward(args)...); DCHECK(!empty()); } }; template struct MapNode 6 * sizeof(void *))>> { struct Impl { using first_type = KeyT; using second_type = ValueT; KeyT first{}; union { ValueT second; }; template Impl(InputKeyT &&key, ArgsT &&...args) : first(std::forward(key)) { new (&second) ValueT(std::forward(args)...); DCHECK(!is_hash_table_key_empty(first)); } Impl(const Impl &other) = delete; Impl &operator=(const Impl &other) = delete; Impl(Impl &&other) = delete; void operator=(Impl &&other) = delete; ~Impl() { second.~ValueT(); } }; using first_type = KeyT; using second_type = ValueT; using public_key_type = KeyT; using public_type = Impl; unique_ptr impl_; const KeyT &key() const { DCHECK(!empty()); return impl_->first; } Impl &get_public() { return *impl_; } const Impl &get_public() const { return *impl_; } MapNode() { } MapNode(KeyT key, ValueT value) : impl_(td::make_unique(std::move(key), std::move(value))) { } void copy_from(const MapNode &other) { DCHECK(empty()); DCHECK(!other.empty()); impl_ = td::make_unique(other.impl_->first, other.impl_->second); } bool empty() const { return impl_ == nullptr; } void clear() { DCHECK(!empty()); impl_ = nullptr; } template void emplace(KeyT key, ArgsT &&...args) { DCHECK(empty()); impl_ = td::make_unique(std::move(key), std::forward(args)...); } }; } // namespace td