Skip to content

Frozen bimap? #22

Description

@Randalphwa

Migrated from the original repository
Original issue: serge-sans-paille/frozen#145
Originally reported by: @RazielXYZ


In a lot of use cases for frozen, such as enum-to-string mappings, it feels like it would be very useful to have the option for looking up values from either side.

Obviously, one could do this by manually making another map with the keys and values swapped, or even use a macro or code generator to do so, but those solutions tend to be either annoying to implement and use, or relatively fickle.

That in mind, I've implemented a quick and "simple" bimap on top of frozen::unordered_map, which can handle constexpr elements, and looks something like this:

template <typename T1, typename T2>
struct swappedPair {
    constexpr std::pair<T2, T1> operator()(const std::pair<T1, T2>& inPair) {
        return {inPair.second, inPair.first};
    }
};

template <typename K, typename V, std::size_t N>
struct FrozenBimap {
    const frozen::unordered_map<K, V, N> left;
    const frozen::unordered_map<V, K, N> right;

    constexpr std::array<std::pair<V, K>, N> makeR(std::pair<K, V> const (&items)[N]) {
        return [] <std::size_t... I>(std::pair<K, V> const (&s)[N], std::index_sequence<I...>) -> std::array<std::pair<V, K>, N> {
            return {swappedPair<K, V>{}(s[I]) ...};
        }(std::forward<std::pair<K, V> const[N]>(items), std::make_index_sequence<N>{});
    }

    constexpr FrozenBimap() = delete;
    constexpr FrozenBimap(std::pair<K, V> const (&items)[N]) :
        left(frozen::unordered_map<K, V, N>{items}),
        right(makeR(items)) {
    }
    constexpr FrozenBimap(std::array<std::pair<K, V>, N> const& items) :
        left(frozen::unordered_map<K, V, N>{items}),
        right(makeR(items)) {
    }
};

Would something like this be useful as a part of frozen proper? I could try to further refine it then do a PR. Note that this version only works with C++20, but I'm pretty sure C++14 would be doable, although not quite as clean on the makeR method's implementation.

Also, obviously because the values are keys for the second map, this would likely be limited to both keys and values being immutable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions