// A example for template
// From <<An introduction to object-oriented programming>> P273
#include <iostream>
#include <string>
#include <list>
using namespace std;
// class Apple
class Apple {
public:
Apple() : variety("generic") {}
Apple(string & v) : variety(v) {}
Apple(const Apple & a) : variety(a.variety) {}
ostream & print_on(ostream & out) {
return out << "Apple: " << variety;
}
private:
string variety;
};
// class Orange
class Orange {
public:
Orange() {}
ostream & write_to(ostream & out) {
return out << "Orange";
}
};
// Common function for output stream
void print(Apple & a, ostream & out) {
a.print_on(out);
}
void print(Orange & r, ostream & out) {
r.write_to(out);
}
// Class Fruit
class Fruit {
public:
virtual void print(ostream & out) = 0;
};
template <class T>
class FruitAdapter : public Fruit {
public:
FruitAdapter(T & t) : the_fruit(t) {}
T & value() {
return the_fruit;
}
virtual void print(ostream & out) {
::print(the_fruit, out);
}
public:
T & the_fruit;
};
template <class T>
Fruit * new_Fruit(T & t) {
return new FruitAdapter<T>(t);
}
int main(int argc, char * argv[])
{
Apple apple;
Orange orange;
list<Fruit *> fruit_list;
fruit_list.insert(fruit_list.end(), new_Fruit(apple));
fruit_list.insert(fruit_list.end(), new_Fruit(orange));
list<Fruit *>::iterator start = fruit_list.begin();
list<Fruit *>::iterator stop = fruit_list.end();
for (; start != stop; start++) {
(*start)->print(cout);
}
return 0;
}