#include <iostream>
#include <memory>
#include <queue>

using namespace std;

class Base {
public:
	Base(int arg): val(arg) {};
	virtual ~Base() = default;
    int val;
};

class Derived1: virtual public Base {
public:
	Derived1(int arg): Base(arg) {};
};

class Derived2: virtual public Base {
	using Base::Base;
};

void doSomething(std::shared_ptr<Base> ptr) {
	cout << "Ptr: " << typeid(ptr).name() << endl;
	cout << "Obj: " << typeid(*ptr).name() << endl;
    cout << "Val: " << ptr->val << endl;
}

void copyPtr(const std::shared_ptr<Base>& in, std::shared_ptr<Base>& out)
{
	std::queue<std::shared_ptr<Base>> q;
	
	q.push(in);
	out = q.front();
	q.pop();
}

int main() {
	std::shared_ptr<Base> ptr;
	
    doSomething(std::make_shared<Derived1>(2));
    doSomething(std::make_shared<Derived2>(3));
    
    copyPtr(std::make_shared<Derived1>(4), ptr);
    doSomething(ptr);
    copyPtr(std::make_shared<Derived2>(5), ptr);
    doSomething(ptr);
}
