2015-05-21 17 views
9

Tôi đang viết một chức năng sẽ nhận được một trong số (std::map, std::multimap, std::unordered_map hoặc std::unordered_multimap). Mã của tôi là như sau:Mẫu chức năng nhận bất kỳ bản đồ chuẩn nào

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; 
      } 
     } 

Mẫu template tham số Map không khái quát cho tất cả các loại bản đồ. Các số std::mapstd::multimap nhận được bốn thông số mẫu và std::unordered_mapstd::unordered_multimap nhận được năm thông số mẫu. Điều này ngụ ý rằng tôi không thể giải quyết vấn đề với tham số mẫu mẫu. Có cách nào để giải quyết vấn đề này với ràng buộc rằng tất cả các bản đồ phải có KeyType = ValeType = Coord không? Tôi không muốn chỉ định rõ ràng các loại thông số trong cuộc gọi đến filter.

Trả lời

1

Mặc dù các lớp mẫu đó có số lượng đối số khác nhau, chúng có mặc định, vì vậy tất cả có thể được khởi tạo chỉ bằng hai. Như vậy, bạn chỉ có thể sử dụng một mẫu variadic, sau đó bất cứ điều gì mà không phải là instantiatable với hai đối số sẽ gây ra một lỗi biên dịch anyway:

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

Giả định bạn không muốn hỗ trợ bản đồ với hàm đặt hàng khác hoặc hàm băm khác với mặc định. Điều đó có vẻ kỳ lạ. – Yakk

4

Chỉ cần viết kiểu đặc điểm riêng của bạn:

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

mà bạn sau đó chuyên cho 5 bản đồ:

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. 

cho phép bạn chấp nhận bất kỳ map, không phân biệt cấp phát, so sánh, hàm băm của nó, vv, miễn là nó là 01./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 */ 
} 

Hoặc bạn có thể rút ngắn thời đó bằng cách chỉ giả định rằng vì tất cả các bản đồ có một key_typemapped_type, xác minh rằng những người cả hai tồn tại và cũng giống như 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 
{ }; 
+0

Không thể suy ra thay thế cho 'Coord', phải chỉ định rõ ràng. –

+0

@RaulAlonso Chỉ cần thêm loại mặc định cho 'Coord', được cập nhật. – Barry

4

Bạn đã gắn thẻ C++ 11 vì vậy tôi sẽ cố gắng sử dụng các tham số mẫu variadic:

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; 
     } 
    } 

} 
Các vấn đề liên quan