Created
February 19, 2014 14:44
-
-
Save vittorioromeo/9093468 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright (c) 2013-2014 Vittorio Romeo | |
// License: Academic Free License ("AFL") v. 3.0 | |
// AFL License page: http://opensource.org/licenses/AFL-3.0 | |
#ifndef SSVU_BIMAP | |
#define SSVU_BIMAP | |
#include <cassert> | |
#include <map> | |
#include <set> | |
#include <utility> | |
#include <algorithm> | |
namespace ssvu | |
{ | |
/// @brief Bi-directional key-value container. | |
/// @details Implemented as a pair of std::map | |
/// @tparam T1 Key/Value type 1 | |
/// @tparam T2 Key/Value type 2 | |
/// @tparam TContainer Underlying container type. Can be std::map, std::unordered_map, ... | |
template<typename T1, typename T2, typename TC1 = std::less<T1>, typename TC2 = std::less<T2>> class Bimap | |
{ | |
public: | |
using key_type = std::pair<T1, T2>; | |
using value_type = std::pair<T1, T2>; | |
using iterator = typename std::set<key_type>::iterator; | |
using const_iterator = typename std::set<key_type>::const_iterator; | |
private: | |
struct ComparerT1 | |
{ | |
inline bool operator()(const T1& mA, const T1& mB) noexcept { return !TC1{}(mA, mB) && !TC1{}(mB, mA); } | |
}; | |
struct ComparerT2 | |
{ | |
inline bool operator()(const T2& mA, const T2& mB) noexcept { return !TC2{}(mA, mB) && !TC2{}(mB, mA); } | |
}; | |
struct Comparer | |
{ | |
inline bool operator()(const key_type& mA, const key_type& mB) noexcept { return TC1{}(mA.first, mB.first); } | |
}; | |
std::set<std::pair<T1, T2>, Comparer> data; | |
public: | |
/// @brief Default constructor. | |
/// @details Initializes an empty Bimap. | |
inline Bimap() = default; | |
/// @brief Initializer list constructor. | |
/// @details Initializes a Bimap from a std::initalizer_list of pairs. | |
/// @param mPairs Initializer list of std::pair<T, U>. | |
inline Bimap(const std::initializer_list<std::pair<T1, T2>>& mPairs) { for(const auto& p : mPairs) this->emplace(p); } | |
/// @brief Emplace a pair in the Bimap. | |
template<typename... TArgs> inline void emplace(TArgs&&... mArgs) { data.emplace(std::forward<TArgs>(mArgs)...); } | |
/// @brief Insert a pair in the Bimap. | |
/// @param mPair std::pair<T, U> to insert. | |
inline void insert(const std::pair<T1, T2>& mPair) { this->emplace(mPair); } | |
/// @brief Erase a pair from the Bimap. | |
/// @param mKey Key of the pair to erase. | |
template<typename T> inline void erase(const T& mValue) { assert(this->has(mKey)); data.erase(data.find } | |
/// @brief Erase a pair from the Bimap. | |
/// @param mKey Key of the pair to erase. | |
inline void erase(const T2& mKey) { assert(this->has(mKey)); map1.erase(*map2.at(mKey)); map2.erase(mKey); } | |
/// @brief Returns a value from the Bimap. | |
/// @param mKey Key of the value to return. | |
inline const T2& at(const T1& mKey) const { return map1.at(mKey); } | |
/// @brief Returns a value from the Bimap. | |
/// @param mKey Key of the value to return. | |
inline const T1& at(const T2& mKey) const { return *map2.at(mKey); } | |
/// @brief Returns a value from the Bimap. (unsafe) | |
/// @param mKey Key of the value to return. | |
inline const T2& operator[](const T1& mKey) noexcept { assert(this->has(mKey)); return map1[mKey]; } | |
/// @brief Returns a value from the Bimap. (unsafe) | |
/// @param mKey Key of the value to return. | |
inline const T1& operator[](const T2& mKey) noexcept { assert(this->has(mKey)); return *map2[mKey]; } | |
/// @brief Looks for a value in the Bimap. | |
/// @param mValue Key of the value to find. | |
inline auto find(const T1& mValue) const -> decltype(std::declval<const decltype(map1)>().find(mValue)) { return map1.find(mValue); } | |
/// @brief Looks for a value in the Bimap. | |
/// @param mValue Key of the value to find. | |
inline auto find(const T2& mValue) const -> decltype(std::declval<const decltype(map2)>().find(mValue)) { return map2.find(mValue); } | |
/// @brief Checks if a value is in the Bimap. | |
/// @param mValue Key of the value to find. | |
inline bool has(const T1& mValue) const { return this->find(mValue) != std::end(map1); } | |
/// @brief Checks if a value is in the Bimap. | |
/// @param mValue Key of the value to find. | |
inline bool has(const T2& mValue) const { return this->find(mValue) != std::end(map2); } | |
/// @brief Returns the first map container. (const version) | |
inline const decltype(map1)& getMap1() const noexcept { return map1; } | |
/// @brief Returns the second map container. (const version) | |
inline const decltype(map2)& getMap2() const noexcept { return map2; } | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment