// // 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 <type_traits> #include <utility> namespace td { template <class KeyT, class Enable = void> struct SetNode { using public_key_type = KeyT; using public_type = const KeyT; using second_type = KeyT; // TODO: remove second_type? KeyT first; const KeyT &key() const { return first; } const KeyT &get_public() { return first; } SetNode() : first() { } explicit SetNode(KeyT key) : first(std::move(key)) { } SetNode(const SetNode &other) = delete; SetNode &operator=(const SetNode &other) = delete; SetNode(SetNode &&other) noexcept { *this = std::move(other); } void operator=(SetNode &&other) noexcept { DCHECK(empty()); DCHECK(!other.empty()); first = std::move(other.first); other.first = KeyT(); } ~SetNode() = default; void copy_from(const SetNode &other) { DCHECK(empty()); first = other.first; DCHECK(!empty()); } bool empty() const { return is_hash_table_key_empty(first); } void clear() { first = KeyT(); DCHECK(empty()); } void emplace(KeyT key) { first = std::move(key); } }; template <class KeyT> struct SetNode<KeyT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void *))>> { struct Impl { using second_type = KeyT; KeyT first; template <class InputKeyT> explicit Impl(InputKeyT &&key) : first(std::forward<InputKeyT>(key)) { 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; }; using public_key_type = KeyT; using public_type = const KeyT; using second_type = KeyT; // TODO: remove second_type? unique_ptr<Impl> impl_; const KeyT &key() const { DCHECK(!empty()); return impl_->first; } const KeyT &get_public() { DCHECK(!empty()); return impl_->first; } SetNode() : impl_() { } explicit SetNode(KeyT key) : impl_(td::make_unique<Impl>(std::move(key))) { } void copy_from(const SetNode &other) { DCHECK(empty()); impl_ = td::make_unique<Impl>(other.impl_->first); DCHECK(!empty()); } bool empty() const { return impl_ == nullptr; } void clear() { DCHECK(!empty()); impl_ = nullptr; } void emplace(KeyT key) { DCHECK(empty()); impl_ = td::make_unique<Impl>(std::move(key)); } }; } // namespace td