Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*--------------bimap.h------------------*/
- #pragma once
- #include <optional>
- #include <string_view>
- #include <memory>
- class BiMap {
- public:
- /**
- * Добавляет в словарь пару "ключ-значение".
- * В случае успеха возвращает true.
- * Возвращает false, если ключ или значение были ранее добавлены.
- *
- * Метод обеспечивает строгую гарантию безопасности исключений
- */
- BiMap();
- BiMap(const BiMap& other);
- BiMap(BiMap&& other) noexcept;
- BiMap& operator=(const BiMap& other);
- BiMap& operator=(BiMap&& other) noexcept;
- bool Add(std::string_view key, std::string_view value);
- /**
- * Возвращает значение, связанное с ключом, либо nullopt, если такого ключа нет
- */
- std::optional<std::string_view> FindValue(std::string_view key) const noexcept;
- /**
- * Возвращает ключ, связанный с value, либо nullopt, если такого значения нет
- */
- std::optional<std::string_view> FindKey(std::string_view value) const noexcept;
- ~BiMap();
- private:
- /* Класс должен использовать идиому Pimpl, поддерживать копирование и перемещение */
- struct Impl;
- std::unique_ptr<Impl> impl_;
- };
- /*--------------bimap.cpp------------------------------------------------------------------------------------------------------*/
- #include "bimap.h"
- #include <unordered_map>
- #include <deque>
- #include <stdexcept>
- // Определение структуры KeyVal
- struct KeyVal
- {
- std::string key;
- std::string value;
- };
- // Определение структуры BiMap::Impl
- struct BiMap::Impl {
- std::unordered_map<std::string_view, std::string_view> key_to_value;
- std::unordered_map<std::string_view, std::string_view> value_to_key;
- std::deque<KeyVal> storage;
- Impl() = default;
- Impl(const Impl& other) {
- key_to_value = other.key_to_value;
- value_to_key = other.value_to_key;
- storage = other.storage;
- }
- Impl& operator=(const Impl& other) {
- if (this != &other) {
- key_to_value = other.key_to_value;
- value_to_key = other.value_to_key;
- storage = other.storage;
- }
- return *this;
- }
- bool Add(std::string_view key, std::string_view value) {
- try {
- if (key_to_value.count(key) > 0 || value_to_key.count(value) > 0) {
- return false;
- }
- storage.push_back({ std::string(key), std::string(value) });
- auto &[storage_key, storage_value] = storage.back();
- key_to_value[storage_key] = storage_value;
- value_to_key[storage_value] = storage_key;
- return true;
- }
- catch (const std::bad_alloc&) {
- // частично внесенные изменения
- key_to_value.clear();
- value_to_key.clear();
- storage.clear();
- throw;
- }
- }
- std::optional<std::string_view> FindValue(std::string_view key) const noexcept {
- auto it = key_to_value.find(key);
- if (it != key_to_value.end()) {
- return it->second;
- }
- return std::nullopt;
- }
- std::optional<std::string_view> FindKey(std::string_view value) const noexcept {
- auto it = value_to_key.find(value);
- if (it != value_to_key.end()) {
- return it->second;
- }
- return std::nullopt;
- }
- };
- // Реализация методов BiMap
- BiMap::BiMap() : impl_(std::make_unique<Impl>()) {}
- BiMap::BiMap(const BiMap& other) : impl_(std::make_unique<Impl>(*other.impl_)) {}
- BiMap& BiMap::operator=(const BiMap& other) {
- if (this != &other) {
- *impl_ = *other.impl_;
- }
- return *this;
- }
- BiMap::BiMap(BiMap&& other) noexcept = default;
- BiMap& BiMap::operator=(BiMap&& other) noexcept = default;
- BiMap::~BiMap() = default;
- bool BiMap::Add(std::string_view key, std::string_view value) {
- return impl_->Add(key, value);
- }
- std::optional<std::string_view> BiMap::FindValue(std::string_view key) const noexcept {
- return impl_->FindValue(key);
- }
- std::optional<std::string_view> BiMap::FindKey(std::string_view value) const noexcept {
- return impl_->FindKey(value);
- }
- /*--------------main.cpp----------------------------------------------------------------------для теста из пачки----*/
- #include <cassert>
- #include <experimental/random>
- #include "bimap.h"
- void TestBenchmarkMove()
- {
- BiMap bimap;
- int N = 3e5;
- for (auto i = 0; i < N; i++) {
- auto key = "key-" + std::to_string(i);
- auto val = "value-" + std::to_string(i);
- bimap.Add(std::string_view(key), std::string_view(val));
- }
- BiMap moved_bimap(std::move(bimap));
- for (auto i = 0; i < N / 1000; i++) {
- int index = std::experimental::randint(0, N);
- auto key = "key-" + std::to_string(index);
- auto val = "value-" + std::to_string(index);
- assert(moved_bimap.FindKey(val) == key);
- assert(moved_bimap.FindValue(key) == val);
- }
- BiMap move_assigned_bimap;
- move_assigned_bimap = std::move(moved_bimap);
- for (auto i = 0; i < N / 1000; i++) {
- int index = std::experimental::randint(0, N);
- auto key = "key-" + std::to_string(index);
- auto val = "value-" + std::to_string(index);
- assert(move_assigned_bimap.FindKey(val) == key);
- assert(move_assigned_bimap.FindValue(key) == val);
- }
- }
- /*--------------main.cpp------------------*/
- #include <cassert>
- #include "bimap.h"
- int main() {
- using namespace std::literals;
- BiMap bimap;
- {
- const bool cat_added = bimap.Add("Cat"sv, "Koshka"sv);
- assert(cat_added);
- assert(bimap.FindValue("Cat"sv) == "Koshka"sv);
- assert(bimap.FindKey("Koshka"sv) == "Cat"sv);
- assert(!bimap.FindKey("Cat"sv));
- assert(!bimap.FindValue("Koshka"sv));
- const bool kitty_added = bimap.Add("Cat"sv, "Kitty"sv);
- assert(!kitty_added);
- assert(bimap.FindValue("Cat"sv) == "Koshka"sv);
- assert(!bimap.FindValue("Kitty"sv));
- }
- BiMap bimap_copy(bimap);
- assert(bimap_copy.FindValue("Cat"sv) == "Koshka"sv);
- assert(bimap_copy.FindKey("Koshka"sv) == "Cat"sv);
- bimap_copy.Add("Dog"sv, "Sobaka"sv);
- assert(bimap_copy.FindValue("Dog"sv) == "Sobaka"sv);
- assert(bimap_copy.FindKey("Sobaka"sv) == "Dog"sv);
- assert(!bimap.FindKey("Sobaka"sv));
- assert(!bimap.FindValue("Dog"sv));
- bimap = std::move(bimap_copy);
- assert(bimap.FindValue("Dog"sv) == "Sobaka"sv);
- assert(bimap.FindKey("Sobaka"sv) == "Dog"sv);
- BiMap moved_bimap(std::move(bimap));
- assert(moved_bimap.FindValue("Dog"sv) == "Sobaka"sv);
- assert(moved_bimap.FindKey("Sobaka"sv) == "Dog"sv);
- BiMap bimap_to_assign;
- bimap_to_assign = moved_bimap;
- assert(bimap_to_assign.FindValue("Dog"sv) == "Sobaka"sv);
- assert(bimap_to_assign.FindKey("Sobaka"sv) == "Dog"sv);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement