#include <iostream>
#include <vector>

template <class T>
struct holder {
    std::vector<T>	data;
};

struct gameboy;

struct ball { ball(gameboy *) {} };
struct door { door(gameboy *) {} };
struct piss { piss(gameboy *) {} };
struct foo {};

struct gameboy
	: private holder<ball>
	, private holder<door>
	, private holder<piss>
{
	template <class T>
	T & push_back()
	{
		holder<T> & ancestor = static_cast<holder<T> &>(*this);	// compile error here if type mismatch
		ancestor.data.push_back(T(this));
		return *ancestor.data.rbegin();
	}

	template <class T>
	typename std::vector<T>::size_type size() const 
	{
		return holder<T>::data.size(); // or you can just ask your ancestor directly
	}
};

int main()
{
	gameboy boy;
	boy.push_back<ball>();
	boy.push_back<door>();
	boy.push_back<piss>();
	boy.push_back<door>();

	std::cout << boy.size<door>() << std::endl;
    // std::cout << boy.size<foo>() << std::endl;   // cannot use foo!

	return 0;
}