簡體   English   中英

將STL迭代器作為特定類型元素的任何容器的函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM