2015-09-23 120 views
0

爲了使用簡化的示例,讓我們考慮一些動物在食物列表中吃一些食物。食物列表針對不同的情況有很多不同的迭代器。虛擬模板設計

class contains_fish 
{ 
    public: 
    bool operator() (const Food& food) const; 
}; 
class is_vegetarian 
{ 
    public: 
    bool operator() (const Food& food) const; 
}; 
class FoodList 
{ 
    private: 
    std::vector<Food> foodItems; 
    public: 
    typedef std::vector<Food>::iterator iterator; 
    typedef std::vector<Food>::const_iterator const_iterator; 
    typedef std::vector<Food>::reverse_iterator reverse_iterator; 
    typedef std::vector<Food>::const_reverse_iterator const_reverse_iterator; 
    typedef boost::filter_iterator<contains_fish,FoodList::iterator> fish_iterator; 
    typedef boost::filter_iterator<contains_fish,FoodList::const_iterator> fish_const_iterator; 
    typedef boost::filter_iterator<contains_fish,FoodList::reverse_iterator> fish_reverse_iterator; 
    typedef boost::filter_iterator<contains_fish,FoodList::const_reverse_iterator> fish_const_reverse_iterator; 
    typedef boost::filter_iterator<is_vegetarian,FoodList::iterator> vegetarian_iterator; 
    typedef boost::filter_iterator<is_vegetarian,FoodList::const_iterator> vegetarian_const_iterator; 
    typedef boost::filter_iterator<is_vegetarian,FoodList::reverse_iterator> vegetarian_reverse_iterator; 
    typedef boost::filter_iterator<is_vegetarian,FoodList::const_reverse_iterator> vegetarian_const_reverse_iterator; 
    //... 
    //... with corresponding begin/end functions : 
    FoodList::iterator begin() { return this->foodItems.begin(); } 
    FoodList::const_iterator begin() const { return this->foodItems.begin(); } 
    //... 
    FoodList::vegetarian_const_reverse_iterator begin_vegetarian_const_reverse() const { return boost::make_filter_iterator<is_vegetarian>(this->foodItems.rbegin(), this->foodItems.rend()); } 
}; 

現在我想給食物列表上的迭代器給每個動物食物(一個虛函數)。這樣的代碼的東西(不工作,由於虛擬模板功能):

class Animal 
{ 
    public: 
    virtual ~Animal() {} 
    template <typename FoodListIterator> 
    virtual void eat(FoodListIterator begin, FoodListIterator end) = 0; 
}; 

class Dog : public Animal 
{ 
    public: 
    virtual ~Dog() {} 
    template <typename FoodListIterator> 
    virtual void eat(FoodListIterator begin, FoodListIterator end) 
    { 
     if(begin == end) 
     std::cout << "Sad day ! Nothing for me..." << std::endl; 
     else 
     { 
     std::cout << "I'm a dog and I'm going to eat :" << std::endl; 
     for(FoodListIterator it = begin; it != end; ++it) 
      std::cout << it->toString() << std::endl; 
     } 
    } 
}; 

void give_fish(std::vector<Animal*>& animals, const FoodList& food_list) 
{ 
    for(unsigned long int i = 0; i < animals.size(); ++i) 
    animals[i]->eat(food_list.fish_begin(), food_list.fish_end()); 
} 

我有太多不同的迭代器來實現每個簽名的虛函數。

如何在不使用C++ 11的情況下優雅地做到這一點?如果它可以幫助,我知道類型的列表(在FoodList中描述的迭代器列表)。

+3

由於您已經在使用Boost,因此您應該可以使用Boost的['any_range']( http://www.boost.org/doc/libs/1_59_0/libs/range/doc/html/range/reference/ranges/any_range.html)或者只是其隨附的'any_iterator'。 – Angew

+0

作爲一般規則,不要將編譯時多態性(模板)與運行時多態性(虛擬調用)混合使用。他們在一起打球不好。 – SergeyA

+0

@Angew:如果我很好理解這個工具,我可以使用'boost :: range_detail :: any_iterator '而不是我的模板類型'FoodListIterator'?但我不明白我必須使用什麼作爲第二個模板類型...: -/ – Caduchon

回答

1

你可以重新組織你的界面使得每個Animal被送到一個單一Food幾乎和一系列的Food S非無形中:

class Animal 
{ 
    public: 
    virtual ~Animal() {} 
    virtual void eat(Food&) = 0; // or Food const& 

    template <typename Iterator> 
    void eat(Iterator begin, Iterator end) { 
     for (; begin != end; ++begin) { 
      eat(*begin); 
     } 
    } 
}; 

但如果你真的需要的整個範圍,你可以使用類似boost::any_range

class Animal 
{ 
public: 
    using FoodRange = boost::any_range<Food, boost::forward_traversal_tag, 
             Food&, std::ptrdiff_t>; 

    virtual ~Animal() {} 
    virtual void eat(FoodRange) = 0; 

    template <typename Iterator> 
    void eat(Iterator begin, Iterator end) { 
     eat(FoodRange{begin, end}); 
    } 
};  
+0

這不是一個真正的解決方案,因爲我的算法使用有關範圍內所有元素的全局信息。 – Caduchon

+0

@Caduchon我......不知道這是什麼意思。 – Barry

+0

如果狗只計算他必須吃的食物並且如果它小於5則添加評論;或者貓在吃之前檢查它是否按照特定的標準進行了訂購。虛擬吃飯功能需要所有元素來完成這項工作。 – Caduchon