接收任何标准映射的函数模板

Function template receiving any standard map

本文关键字:函数模板 映射 标准 任何      更新时间:2023-10-16

我正在编写一个函数,应该接收(std::map, std::multimap, std::unordered_mapstd::unordered_multimap)之一。我的代码如下:

template<template <class, class> class Map, typename Coord>
    inline typename std::enable_if<std::is_arithmetic<Coord>::value>::type 
    filter(Map<Coord, Coord>& map, Coord step = 2) {
            for (auto it = std::begin(map); it != std::end(map);) {
                if (it->second - it->first <= step){
                    it = map.erase(it);
                }
                else
                    ++it;
            }
        }

模板模板参数Map不能泛化到所有类型的映射。std::mapstd::multimap接收4个模板参数,std::unordered_mapstd::unordered_multimap接收5个模板参数。这意味着我不能用模板模板参数解决这个问题。是否有任何方法来解决这个约束,所有地图必须有KeyType = ValeType = Coord ?我不想在调用filter时显式地指定参数类型。

你标记了c++11,所以我会尝试使用可变模板参数:

template<template <class ... > class Map, typename Coord, typename ... MapParms >
inline typename std::enable_if<std::is_arithmetic<Coord>::value>::type
filter(Map<Coord, Coord, MapParms... >& map, Coord step = 2)  
{   
    for (auto it = std::begin(map); it != std::end(map);) 
    {   
        if (it->second - it->first <= step)
        {   
            it = diagram.erase(it);
        }   
        else
        {   
            ++it;
        }   
    }   
}   

写你自己的type trait:

template <typename M, typename COORD>
struct is_map_of_coord : std::false_type { };

然后对5个映射进行专门化:

template <typename COORD, typename C, typename A>
struct is_map_of_coord<std::map<COORD, COORD, C, A>, COORD>
: std::true_type { };
template <typename COORD, typename H, typename K, typename A>
struct is_map_of_coord<std::unordered_map<COORD, COORD, H, K, A>, COORD>
: std::true_type { };
etc.

允许你接受任何map,不管它的分配器,比较器,哈希函数等,只要它的Key/ValueCoord:

template <typename Map, typename Coord = int>
inline typename std::enable_if<
    std::is_arithmetic<Coord>::value &&
    is_map_of_coord<Map, Coord>::value
>::type 
filter(Map& map, Coord step = 2) {
    /* body */
}

或者你可以通过假设所有的地图都有key_typemapped_type来缩短它,验证它们都存在并且与COORD相同:

template <typename...>
using void_t = void;
template <typename M, typename COORD, typename = void>
struct is_map_of_coord : std::false_type { };
template <typename M, typename COORD>
struct is_map_of<M, K, void_t<
    std::enable_if_t<std::is_same<typename M::key_type, COORD>::value>,
    std::enable_if_t<std::is_same<typename M::mapped_type, COORD>::value>
> >
: std::true_type
{ };

尽管这些模板类接受不同数量的参数,但它们都有默认值,因此都可以只用两个实例化。因此,您可以只使用可变参数模板,然后任何不能用两个参数实例化的东西都会导致编译器错误:

template<template <class...> class Map, typename Coord>