2014-03-27 20 views
0

我有一個基類(Container),它擁有std::unique_ptr<Base>矢量中的每種對象(Base項),並且我有一個派生類(FolderOfFolders),它只保存特定項目(Folder項目)。我想使用基於範圍的for來遍歷該特定對象(FolderOfFolder),但我不知道該怎麼做。隨着範圍爲基礎,我可以得到std::unique_ptr<Base>項目,但我想const Folder*的。我知道我需要一個begin(),end()對來提供基於範圍的迭代器for,但是我需要從std::unique_ptr<Base>const Folder*。這可能以某種方式嗎?如何從unique_ptr <Base>的向量中獲取派生迭代器?

class Container : public Base { 
    public: 
    // I want to get back these as Folder* from FolderOfFolders 
    std::vector<std::unique_ptr<Base>> items; 
}; 

class Folder : public Container { 
    public: 
    // I want to call this when I traverse FolderOfFolders with range-based-for 
    void folderMethod(); 
    ... 
}; 

class SystemFolder : public Folder { 
    public: 
    ... 
}; 

class UserFolder : public Folder { 
    public: 
    ... 
}; 

class FolderOfFolders : public Folder { 
    public: 

    // I know that every item is a Folder in items 
    // can I get an iterator to a Folder* ?! 
    iterator begin() { 
     // ??? 
     return items.begin(); 
    } 
    iterator end() { 
     // ??? 
     return items.end(); 
    } 
}; 

我想用它作爲

FolderOfFolders folderOfFolders; 
for (folder : folderOfFolders) 
    folder->folderMethod(); 
+0

你是說,你要確保指針類型的文件夾*的''或只得到來自迭代器的'const Folder *'? – imreal

+1

在我看來,你需要創建自己的自定義迭代器,它用不同的返回類型來包裝向量迭代器。 – IdeaHat

+0

如果你聲明「Folder :: folderMethod()'和'items',你的問題會更清楚。和'基地'。 –

回答

3
#include <boost/iterator/transform_iterator.hpp> 

struct Downcast 
{ 
    typedef const Folder* result_type; 

    result_type operator()(const std::unique_ptr<Base>& p) const 
    { return static_cast<const Folder*>(p.get()); } 
}; 

class FolderOfFolders : public Folder { 
    public: 

    typedef boost::transform_iterator<Downcast, decltype(items)::iterator> iterator; 

    iterator begin() { 
     return iterator(items.begin(), Downcast()); 
    } 
    iterator end() { 
     return iterator(items.end(), Downcast()); 
    } 
}; 

N.B.因爲FolderOfFolders::iterator::operator*按值返回const Folder*,這意味着FolderOfFolders::iterator::reference不是引用類型,所以迭代器只是一個InputIterator,而不是像底層vector::iterator那樣的RandomAccessIterator,但這足夠用於基於範圍的for

但是,這個「一切都是Base,所有集合都是Base的集合」聞起來像Java。有更好的設計。即使你要的Base儲存容器,你可以這樣做,而不必改變迭代器類型:

const Folder& asFolder(const Base& b) { 
    return dynamic_cast<const Folder&>(b); 
} 

class FolderOfFolders : public Folder { 
    public: 

    typedef decltype(items)::iterator iterator; 

    iterator begin() { 
     return items.begin(); 
    } 
    iterator end() { 
     return items.end(); 
    } 
}; 

... 

for (auto& base_ptr : folderOfFolders) 
    asFolder(*base_ptr).folderMethod(); 
+0

哇,我現在就試試這個... –

+0

那麼,編譯工作。完善.. –

0

你的解決方案是引用:

for (auto &folder : folderOfFolders) 
    folder->folderMehod(); 

std::unique_ptr<>對象不是copyables,但你可以迭代與參考綁定。

+1

這避免了試圖複製'文件夾',但它不幫助調用'Folder :: folderMethod()',因爲'文件夾'是'std :: unique_ptr ' –

+0

對不起,我的錯,folderMethod();是在文件夾類不在基地 –