s3rvac
s3rvac

Reputation: 10289

Making a template work with both std::map and std::unordered_map

I have the following template function that returns a copy of the given map with swapped keys and values:

template<typename M>
auto swapKeysAndValues(const M& m) {
    std::map<typename M::mapped_type, typename M::key_type> swapped;
    for (auto& p : m) {
        swapped.emplace(p.second, p.first);
    }
    return swapped;
}

Is there a way of making the above template work for both std::map and std::unordered_map? That is, for std::map<K, V>, it should return std::map<V, K>, and for std::unordered_map<K, V>, it should return std::unordered_map<V, K>.

Upvotes: 12

Views: 2732

Answers (2)

Richard Hodges
Richard Hodges

Reputation: 69864

There are a couple of answers here so I'm not going to cover old ground.

There is however an aspect of this that you ought to consider carefully.

unordered maps are not the same as maps - they have the requirement that a hash function exists for the key (in addition to the equality predicate). As we have seen, it's trivial to write a template function that assumes the defaults, but is that what you want?

If both your K and V have hash functions available, then they are already keys. In that case, isn't what you really wanted a boost::bimap or boost::multi_index_map?

Upvotes: 1

ForEveR
ForEveR

Reputation: 55887

template<template <typename...> class Map, typename K, typename V>
auto swapKeyValues(const Map<K, V>& map)
{
    Map<V, K> result;
    for (const auto& p : map) result.emplace(p.second, p.first);
    return result;
}

Live example

Upvotes: 9

Related Questions