我將如何定義一個函數,該函數將迭代器作爲輸入傳遞給任何類型的STL容器,但僅限於特定模板類型的迭代器。例如:將STL迭代器放在特定類型的元素的任意容器上的函數
形式的任何迭代器std::list<Unit*>::iterator
或std::vector<Unit*>::iterator
我只想確定採取std::list<Unit*>::iterator
的功能,但如果我們切換到不同的STL容器,我不希望有改變我的代碼。
有沒有辦法用模板或其他方式做到這一點?
我將如何定義一個函數,該函數將迭代器作爲輸入傳遞給任何類型的STL容器,但僅限於特定模板類型的迭代器。例如:將STL迭代器放在特定類型的元素的任意容器上的函數
形式的任何迭代器std::list<Unit*>::iterator
或std::vector<Unit*>::iterator
我只想確定採取std::list<Unit*>::iterator
的功能,但如果我們切換到不同的STL容器,我不希望有改變我的代碼。
有沒有辦法用模板或其他方式做到這一點?
您可以使用SFINAE構造,如boost::enable_if,它驗證嵌套的typedef iterator::value_type
是否確實是合適的類型。
template<class T, class Iterator>
typename boost::enable_if<boost::is_same<typename Iterator::value_type, T> >::type
f(Iterator i)
{
/* ... */
}
int main()
{
std::list<int> l;
std::vector<int> v;
f<int>(l.begin()); // OK
f<int>(v.begin()); // OK
std::vector<float> v2;
f<int>(v2.begin()); /* Illegal */
}
這是我從理解「是作爲輸入迭代器在任何類型的STL容器的功能,但只對那些特定的模板類型的」,但我的理解可能是錯誤的。
這對我來說是一個非常有用的答案。謝謝! – 2011-06-16 15:51:07
你只想遍歷my_special_type
的容器?在這種情況下:
template <bool, typename T>
struct enable_if;
template <typename T>
struct enable_if<true, T>
{
typedef T type;
};
template <typename T, typename U>
struct is_same
{
enum {value = false};
};
template <typename T>
struct is_same<T, T>
{
enum {value = true};
};
template <typename Iter>
typename enable_if<is_same<typename Iter::value_type, your_special_type>::value,
void>::type
function(Iter begin, Iter end)
{
// ...
}
有趣!但是,如果函數與錯誤類型一起使用,會發生什麼?對不起,如果這是微不足道的。我仍然在學習模板。 – RyanG 2010-12-04 17:42:37
模板的另一種方式是在條件不滿足時觸發靜態斷言。
#include <iterator>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
template <class Type, class Iter>
void foo(Iter from, Iter to)
{
BOOST_STATIC_ASSERT((boost::is_same<typename std::iterator_traits<Iter>::value_type, Type>::value));
//...
}
int main()
{
int arr[10];
foo<int>(arr, arr + 10); //OK
foo<double>(arr, arr + 10); //triggers static assertion
}
如果您不想使用模板,那麼也可以使用類型擦除來編寫「any_iterator」。例如,像這樣的:http://stlab.adobe.com/classadobe_1_1any__iterator.html
除了依靠SFINAE現有的答案,一個簡單的近似值是簡單地定義函數取任意模板類型的迭代器:
template <typename Iter>
void function(Iter first, Iter last){
Unit* val = *first;
}
這有一些缺點。與SFINAE解決方案(例如boost::enable_if
)不同,這不會給你確切的你所要求的。只要Iter
類型的對象可以被取消引用,就可以編譯,產生一個值,可以轉換爲Unit*
,這是不完全相同的事情。您不能保證Iter
是完全符合STL標準的迭代器(它可能只是另一種類型,它定義了operator*
),或者它的值類型精確地爲Unit*
。
另一方面,它更簡單。
嗯,我會使用的情況下,簡單的typedef,你只需要一個容器類型的時候(如果我理解你的用例,正確是這種情況)
template <class T>
class ContainerIterator
{
Container();
public:
typedef std::list<T>::iterator type;
}
//usage:
void function(ContainerIterator<YourType>::type begin, ContainerIterator<YourType>::type end)
{
//...
}
稍後切換容器,只需更改typedef中的容器類型即可。
`std :: list`? STL容器中的原始指針?爾加! :) – 2010-12-04 19:22:37