如何创建一个带有map或unordered_map的函数?

时间:2014-09-09 16:43:01

标签: c++ templates

我正在实施一些基于模板的序列化。我为std::map实现了模板化函数,但现在我正在使用std::unordered_map。我宁愿不复制&粘贴整个函数,只需更改参数类型即可。有没有办法制作一个只采用地图或无序地图的模板?

5 个答案:

答案 0 :(得分:4)

template <typename MAP>
void generic_foo(MAP& map)
{
    // generic implementation of your function
    // that works with unordered_map and map

    using K = typename MAP::key_type;
    using T = typename MAP::mapped_type;
}

// matches any possible implementation of std::unorderd_map
template <class Key,                                    
          class T,                                   
          class Hash,                       
          class Pred,                  
          class Alloc>
void foo(std::unordered_map<Key, T, Hash, Pred, Alloc>& m)
{
    // signature matched! forward to your implementation
    generic_foo(m);
}

// matches any possible implementation of std::map        
template <class Key,                                    
          class T,                          
          class Compare,                  
          class Alloc>
void foo(std::map<Key, T, Compare, Alloc>& m)
{
    // signature matched! forward to your implementation
    generic_foo(m);
} 

LIVE DEMO

答案 1 :(得分:2)

简单地重载该函数作为非模板化函数,其中一个重载用于std::map而另一个用于获取std::unordered_map。让这两个函数调用一个隐藏的template,它只能被它们调用。一种方法是将其隐藏在匿名namespace

答案 2 :(得分:1)

使用 C++20 概念

要特别支持 favoritestd::map

std::unordered_map

代码:https://godbolt.org/z/MrsaGn


支持任何表现为映射类型的类型:

template<typename T> struct is_unordered_map
   : public std::false_type {};

template<typename... Args>
struct is_unordered_map<std::unordered_map<Args...>>
   : public std::true_type {};

template<typename T> struct is_map
   : public std::false_type {};

template<typename... Args>
struct is_map<std::map<Args...>>
   : public std::true_type {};

template<typename C>
concept UnorderedMap = is_unordered_map<C>::value;

template<typename C>
concept Map = is_map<C>::value;

template<typename C>
concept MappingContainer =
    Map<C> || UnorderedMap<C>;

void foo(const MappingContainer auto& m) { ... }

代码:https://godbolt.org/z/jPfMhT

答案 3 :(得分:0)

#include<type_traits>
template<typename T>
void foo(T t){
    static_assert(std::is_same<T, std::map</*some_type*/>::value
               || std::is_same<T, std::unordered_map</*some_type*/>::value,
                  "Foo can only get std::map or std::unordered_map.");
}

答案 4 :(得分:0)

以下是从std::mapstd::unordered_map提取键/值的示例

template <typename M>
std::unordered_set<typename M::key_type> GetMapKeys(const M& a_map) {
  std::unordered_set<typename M::key_type> keys;
  for (auto const& e : a_map) {
    keys.emplace(e.first);
  }
  return keys;
}

template <typename M>
std::vector<typename M::mapped_type> GetMapValues(const M& a_map) {
  std::vector<typename M::mapped_type> values;
  values.reserve(a_map.size());
  for (auto const& e : a_map) {
    values.push_back(e.second);
  }
  return values;
}