我正在实施一些基于模板的序列化。我为std::map
实现了模板化函数,但现在我正在使用std::unordered_map
。我宁愿不复制&粘贴整个函数,只需更改参数类型即可。有没有办法制作一个只采用地图或无序地图的模板?
答案 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);
}
答案 1 :(得分:2)
简单地重载该函数作为非模板化函数,其中一个重载用于std::map
而另一个用于获取std::unordered_map
。让这两个函数调用一个隐藏的template
,它只能被它们调用。一种方法是将其隐藏在匿名namespace
。
答案 2 :(得分:1)
要特别支持 favorite
和 std::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) { ... }
答案 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::map
或std::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;
}