2015-04-02 41 views
4

我想知道是否有辦法創建一個模板函數,它需要引用任何特定類型的集合。即是這樣的:是否有可能擁有任何類型T的集合的C++模板函數?

class Bob 
{ 
    public: 
    int age; 
    int height; 
} 

template<class T> 
void functionWhichIteratesOverBobs(T &bobs) 
{ 
    int totalAge = 0; 
    for(auto &bob: bobs) 
    { 
     totalAge += bob.age; 
    } 
} 

基本上是有它返回一個迭代到T

的方式,在模板函數的定義,要求T的一個開始()和end()函數我已經看到了以下問題,但這需要一個函數,它接受一個開始和結束,即

std::vector<Bob> bobs; 
functionWhichIteratesOverBobs(bob.begin(), bob.end()); 

當我想的是:

std::vector<Bob> bobs; 
functionWhichIteratesOverBobs(bobs); 

Function that takes an STL iterator over ANY container of a elements of a specific type

+0

「要求T」...那T是什麼? – 2015-04-02 03:49:41

+0

修正了上面的句子。 – bpeikes 2015-04-02 04:40:23

+0

這是爲了提供重載或提供更好的錯誤消息嗎? – 2015-04-02 04:42:28

回答

1

如果你正在尋找保持超載設置無污染,使用表達SFINAE像這樣:

template<class T> 
void functionWhichIteratesOverBobs(T &bobs) 
    -> decltype(std::begin(bobs), std::end(bobs), void()) { 
    // [..Range based for over bobs..] 
} 

但是要記住的是你所顯示的功能模板將沒有一個實例錯誤,如果給出了錯誤的參數,所以這是目前多餘的 - 直到你開始超載functionWhichIteratesOverBobs

+0

這並不是在範圍內檢查可用性的正確方法。 – 2015-04-02 08:50:39

+0

@ T.C。你是說你應該檢查'* std :: begin(bobs)'這樣的表達式嗎? – Columbo 2015-04-02 10:38:25

+0

不是。我指的是ADL找到正確的'begin()'和'end()'的情況。 – 2015-04-02 10:39:21

0

C++的概念Container有一個成員類型value_type所包含元素的類型,所以你可以使用SFINAE就像你有一個迭代器 - 這是更簡單,因爲你並不需要使用iterator_traits

template<class T> 
auto functionWhichIteratesOverBobs(T &bobs) 
    -> std::enable_if_t<std::is_same_v<typename T::value_type, Bob>> 
{ 
    // ... 
} 

請注意,這不適用於原始數組;如果你希望這些工作,你會用decltype(std::begin(bobs))iterator_traits

template<class T> 
auto functionWhichIteratesOverBobs(T &bobs) -> std::enable_if_t<std::is_same_v< 
    typename std::iterator_traits<decltype(std::begin(bobs))>::value_type, Bob>> 
{ 
    // ... 
} 
0

是。這是可能的。

由於Ed S. comment,只是使用你在你的問題中寫的相同功能。如果bobs沒有begin()end(),則編譯器會通過生成錯誤來通知您。
Demo

相關問題