【发布时间】:2015-12-21 01:28:47
【问题描述】:
为了使用一个简化的示例,让我们考虑一些动物吃食物列表中的某些项目。食物列表针对不同情况有很多不同的迭代器。
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 中描述的迭代器列表)。
【问题讨论】:
-
既然你已经在使用 Boost,你应该可以使用 Boost 的
any_range或者只是它附带的any_iterator。 -
作为一般规则,不要将编译时多态性(模板)与运行时多态性(虚拟调用)混合。他们在一起玩得不好。
-
@Angew : 如果我很了解这个工具,我可以使用
boost::range_detail::any_iterator<Food,Something>代替我的模板类型FoodListIterator吗?但我不太明白我必须使用什么作为第二种模板类型......:-/
标签: c++ templates virtual c++98