#include <iostream>
#include <vector>
#include <memory>
using namespace std;

struct A { void what_type() { cout<<"A"<<endl; }};
struct B { void what_type() { cout<<"B"<<endl; }};
struct U { void what_type() { cout<<"U"<<endl; }};
struct V { void what_type() { cout<<"V"<<endl; }};

class MyCommonAncestor {
public:  
    virtual void common_operation1()=0;
    virtual ~MyCommonAncestor() {}
}; 

template <class X, class Y> 
class MyTemplateClass : public MyCommonAncestor {
    X myx; 
    Y myY; 
public:  
    void common_operation1() override {  // addresses specific objects of type X and Y
    	myx.what_type();
    	myY.what_type();
    }; 
    X operation2(const Y& y) {}; 
    ~MyTemplateClass() {   // to demonstrate automatic destruction for shared ptr
    	cout<<"object destroyed"<<endl;
    } 
};

int main() {
	vector<shared_ptr<MyCommonAncestor>> myVector; 
	myVector.push_back(make_shared<MyTemplateClass<A,B>>()); 
	myVector.push_back(make_shared<MyTemplateClass<U,V>>()); 
	for (auto& x: myVector)
	    x->common_operation1(); 
	return 0;
}