2012-04-05 63 views
6

我有一個類,其中包含boost::shared_ptrs到另一個類的對象的列表。shared_ptr的容器,但迭代原始指針

允許訪問列表中的元素的類成員函數返回原始指針。爲了一致性,我還希望能夠使用raw指針而不是shared_ptrs進行迭代。所以當我解引用列表迭代器時,我想獲取原始指針,而不是shared_ptr

我想我需要爲此編寫一個自定義迭代器。它是否正確?如果有的話可以有人指出我正確的方向 - 我從來沒有這樣做過。

+1

請記住,'shared_ptr'就像常規指針('* p'和'p->'都做正確的事情)。 – GManNickG 2012-04-05 20:56:53

+0

我可能是錯的,但提供原始指針和智能指針看起來像是在尋找麻煩。特別是,如果原始指針允許寫入。你在尋找什麼樣的迭代器?如果我是你,我可能會從最簡單的例如'ForwardIterator'開始。 – dirkgently 2012-04-05 21:07:10

+0

我知道'shared_ptr'與'* p'和'p->'表現得一樣。有一段時間,我並沒有真正意識到差異。但是當涉及到用戶界面時,這是一個問題。 API中的其他函數將指針作爲參數。因此,如果用戶從迭代器獲取對象,則需要使用'it-> get()'獲取原始指針。我認爲這並不重要,但從最終用戶的角度來看,用戶甚至不應該知道底層對象由'shared_ptr'保存。所以我想在整個圖書館中保持一致。 – 2012-04-05 21:14:26

回答

5

下面是一個使用Boost transform_iterator一個選項:

#include <list> 
#include <boost/iterator/transform_iterator.hpp> 
#include <tr1/memory> 
#include <tr1/functional> 

using std::list; 
using std::tr1::shared_ptr; 
using boost::transform_iterator; 
using boost::make_transform_iterator; 
using std::tr1::mem_fn; 
using std::tr1::function; 

struct Foo {}; 

struct Bar 
{ 
    typedef shared_ptr<Foo> Ptr; 
    typedef list<Ptr> List; 
    typedef function< Foo* (Ptr) > Functor; 
    typedef transform_iterator< Functor, List::iterator > Iterator; 

    Iterator begin() 
    { 
    return make_transform_iterator(fooptrs.begin(), mem_fn(&Ptr::get)); 
    } 

    Iterator end() 
    { 
    return make_transform_iterator(fooptrs.end(), mem_fn(&Ptr::get)); 
    } 

    List fooptrs; 
}; 

C++ 11就可以很容易地消除function包裝,但我沒有方便的編譯器來測試它。你也可以使用類型擦除,如果你認爲有必要隱藏了具體類型的Iterator(我認爲Adobe提供免費的any_iterator類模板用於此目的。)

+2

+1,如果獲得引用而不是指針是可以接受的(我不明白爲什麼它不應該是這樣),Boost也帶有['indirect_iterator <>'](http://www.boost.org/庫/迭代器/ DOC/indirect_iterator.html)。 – ildjarn 2012-04-05 22:11:44

+0

完美。很好的例子,很好的答案。 – 2012-04-07 00:01:35

1

我有時看到有人伸手的boost::shared_ptr STL容器時,實際上不太明顯且相對較少的已知boost::ptr_container可能是更好的選擇。

這可能是也可能不是這種情況之一,但考慮到ptr_container類的一個很好的屬性是它們的迭代器有an "extra" indirection,這有助於保持事物的清潔和安全。

+0

是的,這是真的。然而,在這種情況下,實際上會共享所有權。 – 2012-04-05 23:59:30

相關問題