2012-10-03 86 views
0

基本上,我試圖寫有一個通用的迭代的基類。C++虛擬的boost ::任何繼承

因此很明顯,模板虛擬功能不起作用,這就是爲什麼我想的boost ::任何,但它仍然不會重載Iterator的get()方法(它繼續拋出下面定義的Exception)。我似乎也無法使其成爲純虛擬的,因爲編譯器抱怨'虛擬迭代器begin()= 0;' (它表示'不能創建抽象類Iterator的實例')。

我有非常具體的限制,我必須/要堅持,所以可能會考慮替代解決方案的問題,但可能無法使用。

下面是代碼的一部分:

template <class T, class C> 
    class Iterator 
    { 
    public: 
     virtual T& operator*() { T *t = boost::any_cast<T>(&get()); return *t; }; 
     virtual boost::any& get() { throw new Exception("get not overridden!!"); }; 
     //virtual boost::any& get() = 0; 
    protected: 
     C::iterator iter; 
    }; 

    template <class T> 
    class VectorIterator: public Iterator<T, std::vector<T> > 
    { 
    public: 
     VectorIterator(std::vector<T>::iterator iterator): Iterator<T, std::vector<T> >(iterator) { }; 
     virtual boost::any& get() { return *iter; }; 
    }; 

    template <class Value, class Container> 
    class Repository 
    { 
    public: 
     typedef Iterator<Value, Container> iterator; 

     virtual iterator begin() = 0; 
     virtual iterator end() = 0; 
    }; 


    class SomeRepository : public Repository<RandomClass, std::vector<RandomClass> > 
    { 
    public: 
     iterator begin() { return VectorIterator<RandomClass>(items.begin()); }; 

     iterator end() { return VectorIterator<RandomClass>(items.end()); }; 
    } 

那麼,爲什麼沒有工作,(如何)可以解決呢? PS:我知道這與另一個問題非常相似,但我無法準確地將其納入評論中,而且我不知道我還能夠把它放在哪裏。

UPDATE:

所以我設法讓GET推測出來的東西()返回一個void(EWW)指針和忘掉的boost ::任何。但它仍然調用Iterator :: get而不是VectorIterator :: get(正如我原來的問題)(當我嘗試使用* someRepository.begin())時,有人知道爲什麼嗎?

+0

我很好奇。這應該達到什麼目的?如果你想在迭代器上輸入erase,那麼有更好的方法可用。 – pmr

+7

'拋出新的異常(...);' - 請不要... – Xeo

+0

@pmr我們的代碼中存在迭代通過Repository的所有元素的現有功能,我認爲更好的方法是創建一個這個泛型迭代器。 – Dukeling

回答

0

如果你在'iterator begin()'中返回Iterator(所以按值返回),它會將返回值轉換爲Iterator,因此它不再是VectorIterator類型,顯然它不會調用VectorIterator的get方法至少這是我的想法)。通過引用或指針返回應該工作得很好。

現在我只需要弄清楚一個解決方法。由於我在VectorIterator :: begin()中返回一個局部變量,因此通過引用返回將無法工作。我想我必須通過指針返回,除非別人有更好的建議。

+0

通過boost :: shared_ptr返回可能是一個更好的主意。 – Dukeling

3

您無法從*iter初始化boost::any&,就像您無法從int類型的值初始化float&一樣。在這兩種情況下都沒有所需類型的實際對象可以參考。

您可以更改get返回boost::any(在這種情況下,從*iter轉換會發生),但隨後你的operator*有它要參考(再次,引用類型)的T的問題需要活得比功能呼叫。一種解決方案是在某處存儲調用get的結果,或者通過使operator*返回值(T)而不是參考文件(T&)來執行與get相同的更改。這些將是價值語義,而不是對底層容器的「淺」視圖。分配operator*的結果,假設它是正確的,不會影響容器的元素。

另一種可能性是使get返回boost::any,該boost::any保證在元素中存儲淺視圖,例如,

virtual boost::any get() { return &*iter; } 

return boost::ref(*iter);是另一種可能性)

必須多加然後採取內部operator*正確恢復的預期值,例如return *boost::any_cast<T*>(get());(或return boot::any_cast<boost::reference_wrapper<T> >(get()).get();)。這有引用語義,其中返回T&會很好。對operator*結果的操作可能會影響容器的元素。