2011-04-20 96 views
0

這是可以做到的,如果沒有拷貝集裝箱的數據?:STL迭代器和模板

template<typename T> //we know only the type return by iterator 
class Foo { 
private: 
    I b; //or some base class of iterator or own generic iterator 
    I e; //what should be 'I'? 
public: 
    template<typename I> 
    Foo(begin, end) { 
     b = begin; 
     e = end; 
    } 
    void find(T value) { 
     while(b != e) { 
      ... 
      ++b; 
     } 
     return NULL; 
    } 
}; 
//... 
//this can't be changed 
std::vector<int> vec; 
Foo<int> foo1(vec.begin(), vec.end()); 
std::list<double> list; 
Foo<double> foo2(list.begin(), list.end()); 
+2

@samadhi:是*什麼*可能沒有複製容器的數據? – phooji 2011-04-20 19:19:47

+1

就像我在你的最後一個問題中問的那樣:爲什麼?什麼是隨機限制來編寫異端代碼?無論如何,你想要類型擦除。 – GManNickG 2011-04-20 19:21:07

+0

我不明白..您想做什麼? – 2011-04-20 19:21:14

回答

1

如果您確實希望能夠聲明僅與容器中包含的數據類型相關的模板,並且您希望能夠將任何類型的迭代器(即迭代器)存儲到任何類型的容器),解決方案是在迭代器上執行類型擦除

如果您可以將一些外部庫引入到adobe庫中,如any_iterator。基本上你定義一個基類定義,你需要用動態的多態性(即虛擬方法)的迭代器接口,然後實現與採取適當類型的模板界面:

template <typename T> 
struct any_iterator { 
    // all typedefs for an iterator here, including: 
    typedef T value_type; 

    virtual ~any_iterator() {} 
    virtual any_iterator& operator++() = 0; 
    virtual value_type& operator*() = 0; 
    // ... rest of the methods 
}; 
template <typename Iterator> 
class any_iterator_impl : any_iterator< typename Iterator::value_type > { 
    iterator it; 
public: 
    // all the typedefs 
    typedef Iterator iterator; 
    typedef typename iterator::value_type value_type; 

    // actual implementation of the interface 
    any_iterator_impl(Iterator it) : it(it) {} 
    virtual any_iterator_impl& operator++() { ++it; return *this; } 
    virtual value_type& operator*() { return *it; } 
    // ... and all the rest of the interface 
}; 

,然後用它在你的類:

template <typename T> 
class Foo { 
    std::unique_ptr<any_iterator> it, end; // in real code use smart pointers here 
public: 
    template <typename Iterator> 
    Foo(Iterator b, Iterator e) { 
     static_assert(is_same< typename Iterator::value_type, T>::value); 
     it = new any_iterator_impl<Iterator>(begin); 
     end = new any_iterator_impl<Iterator>(end); 
    } 
    // rest of the class 
}; 

的代碼片段只用於展覽,他們不是生產代碼,沒有被編譯,並有相當數量的不做的(裸指針,迭代器可以成爲在任何時候無效在對象的生命週期中...),但是打算給y ou一個想法,你需要在迭代器上執行類型擦除。然後,再看看鏈接的adobe庫,以獲得更深思熟慮的提議。

如果您對此感到好奇,則採用與std::functionboost::any相同的方法。其中一個優點是,您可以在不同情況下使用不同系列的迭代器實際使用相同的Foo類。另一方面,它需要動態調度,但在大多數情況下這應該不成問題。

2

鑑於你試圖調用構造函數的方式:

std::vector<int> vec; 
Foo<int> foo1(vec.begin(), vec.end()); 
std::list<double> list; 
Foo<double> foo2(list.begin(), list.end()); 

...你會做到這一點:

template<typename Iter> //we know only the type return by iterator 
class Foo { 
private: 
    Iter b; //or some base class of iterator or own generic iterator 
    Iter e; //what should be 'I'? 

也就是說,如果是存儲在您的類迭代器在所有。大多數時候,你不會。除了在許多情況下迭代器至少在預期時間內失效,這只是一個笨拙的設計。

1

您的代碼似乎沒有多大意義。我傾向於同意GMan的看法,即你想要做的事可能沒有用。但是,有些情況下,模糊的相似的事情是有道理的。當他們這樣做,您通常使用迭代器類型爲模板參數:

template<class inIt> 
class Foo { 
    inIt begin; 
    inIt end; 
public: 
    Foo(inIt b, inIt e) : begin(b), end(e) {} 
    bool find(typename inIt::value_type v) { 
     while (b!=e) { 
      if (*b == v) 
       return true; 
      ++b; 
     } 
     return false; 
    } 
}; 

這並不取決於包含一個typedef其value_type的迭代器類型,這是迭代器標準的容器,如向量和列表也是如此。你可以(可以)編寫你自己的迭代器,但它不會這樣做,這會使得這樣的代碼變得不可能(當然這就是標準庫的工作方式)。