2017-08-09 109 views
4

可能有很多情況下,我們想要在與映射類型無關的std::mapstd::unordered_map上執行某種操作,該操作完全相同。讓我們看看下面的例子:接收通用映射作爲參數的模板函數

#include <map> 
#include <unordered_map> 
#include <iostream> 

template< template <typename,typename> class Container > 
void printMap(Container<int, long> inputMap, bool additionalParam = false) 
{ 
    for (const pair<int,long> p : inputMap) 
     cout<<p.first <<","<< p.second <<std::endl; 
} 

int main() 
{ 
int a = 1; 
long b = 2; 
map<int,long> map1; 
map1.emplace(a,b); 
unordered_map<int,long> map2; 
map2.emplace(a,b); 
printMap(map1); 
printMap(map2); 

return EXIT_SUCCESS; 
} 

如果我嘗試編譯上面的例子,我有這樣的:

error: no matching function for call to ‘printMap(std::map<int, long int>&)’ 

我讀到這個post使用模板的模板。什麼是正確的方法來做到這一點?

+0

['std :: map'](http://en.cppreference.com/w/cpp/container/map)有兩個以上的模板參數。你還有一個'比較'類型和'Allocator'類型。你必須指定所有的,甚至是默認的。 –

+0

請注意,您的代碼將正常工作來C++ 17;以下解決方案都適用於C++ 14及更低版本。 –

回答

4

嘗試

template< template <typename...> class Container, typename ... Ts > 
void printMap(Container<int, long, Ts...> inputMap, 
       bool additionalParam = false) 

的(大)的問題在你的代碼是std::mapstd::unordered_map是模板類有四個(而不是兩個)模板參數。第3和第4個有默認值,所以你可以定義一個std::map對象

std::map<int, long> map1; 

但是,使用默認參數,你將它定義爲

std::map<int, long, std::less<int>, 
      std::allocator<std::pair<const int, long> >> map1; 

(PS:或者你可以把它簡單並且使用auto,如在Semyon Burov的解決方案中; +1)

5

編譯器不能推導出模板參數,如果你這樣定義的話。 嘗試使用:

template<typename Map> 
void printMap(const Map& map, bool additionalParam = false) { 
    for (const auto& p : map) 
     cout<<p.first <<","<< p.second <<std::endl; 
} 

如果需要檢查,也Map正是Map<int, long int>,然後添加靜態斷言的函數體:

static_assert(std::is_same< typename Map::key_type, int >::value && 
         std::is_same< typename Map::mapped_type, long >::value, "!"); 
+0

我添加了一個'static_assert'來維護類型約束。 –

+0

@HenriMenke個人而言,我沒有看到能夠打印任何類型的地圖而不是'Map '的任何問題。 –

+0

我也沒有,但它是問題的一部分,地圖專用於'int'和'long'。 –

0

試試這個:

template<class Container> 
void printMap(const Container& inputMap) 
{ 
    using Key = typename Container::key_type; 
    using Value = typename Container::mapped_type; 
    for (const std::pair<Key,Value> p : inputMap) 
     std::cout << p.first << "," << p.second << std::endl; 
} 

或更好,只是:

template<class Container> 
void printMap(const Container& inputMap) 
{ 
    for (const auto& p : inputMap) 
     std::cout << p.first << ","<< p.second << std::endl; 
} 
+0

@EdgarRokyan:哦,是的,沒關係,我只是有點說明了一點。但是,是的。 – einpoklum