2011-09-30 71 views
2

我想知道如何編寫一個函數,可以接受作爲參數的一個關聯容器,它本身接受兩個或多個模板參數。例如,如果我想編寫一個適用於std :: map的函數,則可以編寫如下所示的內容。關聯容器作爲函數模板參數

template <class Map, class Key, class Value, class Compare, class Allocator> 
void foo(Map<Key, Value, Compare, Allocator>& map); 

但是,這對boost :: unordered_map不起作用,因爲boost :: unordered_map接受5個模板參數。我可以將地圖作爲單個模板參數接受,並使用它應該支持的特徵以便稍後推導出鍵和值類型,但對於嵌套地圖,代碼變得非常冗長且難以維護。有沒有更簡單的方法來編寫這樣的函數,但仍然可以用於任何接受大於或等於2的模板參數的任何關聯容器?

請注意,接受迭代器而不是容器作爲參數是不夠的,因爲我需要更多關於迭代器在其上運行的容器的信息,而不是迭代器可以提供的信息。

非常感謝!

回答

2

爲什麼不直接使用簡單的方法用一個模板參數:

template <typename C> void foo(const C & container) 
{ 
    typedef typename C::key_type key_type; 
    typedef typename C::mapped_type mapped_type; 

    // etc. 
} 

你可以添加一些成員類型檢查typetraits是你想要的那些成員類型存在額外的檢查,但可能不會放棄任何額外的好處。

或者,你可以做一些通用的模式匹配,雖然只帶班,而不是功能:

template <typename> struct AtLeastTwo; 

template <typename K, typename V, typename ...Args> 
struct AtLeastTo<K, V, Args...> 
{ 
    // now have types K and V 
}; 

typedef std::unordered_map<int, Foo, MyHash> map_type; 
AtLeastTwo<map_type> m; 
// ... 
+0

對於嵌套地圖,代碼變得非常冗長,特別是如果內部地圖的外部地圖類型不同。提取所有正確的類型需要使用Boost.TypeTraits進行大量的類型操作。我只是想知道是否有一種更簡單的方法來做到這一點,而不使用特質來反思價值觀,但我想不是。 –

+0

嵌套地圖添加的複雜性究竟是什麼?我不確定你想要達到什麼目的;通過觀察它,任何涉及的類型本身是否是地圖都無關緊要。 –

+0

是的,但如果我需要迭代器來處理外部映射和內部映射中的類型,無論它們的const限定或它們是否爲指針或引用,都需要使用多個重載方法創建實用程序類,以完成一些簡單的任務。 –

0

A型不傳達它是否是一個關聯序列信息,這是一個語義意義。如果你不想支持各種關聯序列,按照標準接口,最好的選擇是使用單個模板參數,並使用特徵來反思其鍵/值類型等等。

+0

這就是我現在正在做的,但是支持使用特徵的嵌套地圖的樣板代碼本身就是幾百行,所以我想知道是否有更簡單的方法來解決這個問題。然而,在閱讀了兩個答案之後,我認爲沒有更簡單的方法。 –