[英]Non-template function that processes any container of elements of specific type
[英]Function that takes an STL iterator over ANY container of a elements of a specific type
我如何定義一個函數,它將迭代器作為輸入作為任何類型的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容器的輸入,但僅限於特定模板類型的那些”,但我的解釋可能是錯誤的。
除了依賴於SFINAE的現有答案之外,更簡單的近似是簡單地定義函數以將任意模板類型作為迭代器:
template <typename Iter>
void function(Iter first, Iter last){
Unit* val = *first;
}
這有一些缺點。 與SFINAE解決方案(例如boost::enable_if
)不同,這並不能完全滿足您的要求。 只要Iter
類型的對象可以被解引用而產生可轉換為Unit*
的值,這就編譯,這不是完全相同的事情。 您無法保證Iter
是完全符合STL的迭代器(它可能只是另一種定義operator*
類型),或者它的值類型是Unit*
精確。
另一方面,它更簡單。
您只想迭代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)
{
// ...
}
模板的另一種方法是在不滿足條件時觸發靜態斷言。
#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
那么我會在你當時只需要一個容器類型的情況下使用一個簡單的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中的容器類型即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.