虚拟模板设计

时间:2015-09-23 16:09:17

标签: c++ templates virtual c++98

为了使用简化的例子,让我们考虑一些动物在食物清单中吃一些食物。食物清单在不同的情况下有很多不同的迭代器。

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中描述的迭代器列表)。

1 个答案:

答案 0 :(得分:1)

您可以重新组织界面,以便每个<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:fillViewport="true" tools:context="com.cecode.www.gjcode.MainTypes" android:animateLayoutChanges="true"> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:gravity="center" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Options Menu(placeholder)" android:id="@+id/optionsBtn" /> <Button android:layout_width="400dp" android:layout_height="80dp" android:text="Top Text" android:id="@+id/button1" android:layout_marginTop="110dp" /> <Button android:layout_width="400dp" android:layout_height="80dp" android:text="placeholder text" android:id="@+id/button2" android:layout_marginTop="20dp" /> <Button android:layout_width="400dp" android:layout_height="80dp" android:text="placeholder text" android:id="@+id/button3" android:layout_marginTop="20dp" /> <Button android:layout_width="400dp" android:layout_height="80dp" android:text="placeholder text" android:id="@+id/button4" android:layout_marginTop="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="mid text" android:id="@+id/textView3" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="50dp" android:orientation="vertical"> <!-- add your button here --> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="bottom text" android:id="@+id/textView4" /> </LinearLayout> </ScrollView> 虚拟地提供一个Animal,并且非虚拟地提供一系列Food

Food

虽然如果你真的需要整个范围,你可以使用类似boost::any_range的东西:

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);
        }
    }
};