// Paolo Medici 
// University of Parma

#include <typeinfo>

/// An Omogeneous Safe Type Reference Container
class ref_container {
 void *m_data;
 const std::type_info * m_info;
 
template<class T>
 void assign (T * data)
	{
	m_info = &typeid(T);
	m_data = reinterpret_cast<void *>(data);
	}

 template<class T>
 T *get() const
	{
	if(*m_info == typeid(T))
		return reinterpret_cast<T *>(m_data);
	else
		throw std::bad_cast();
	}

public:
 ref_container() : m_data(0), m_info(0) { }
 template<class T>
 explicit ref_container(T & data) { assign(&data); }

 template<class T>
 inline void operator = (T & data) { assign(&data); }

 template<class T>
 inline operator T () const { return *get<T>(); }
	 
};

///////////////////////////////////////////// TEST ///////////////////

#include <iostream>
#include <vector>

void foo(const ref_container & c)
{
std::cout << int(c) << std::endl;
}

int main()
{
std::vector<ref_container> a;
int X;
double Y;
X = 1;
Y = 1.0;

a.push_back(ref_container(X));
a.push_back(ref_container(Y));

foo(a[0]);	// works
foo(a[1]);	// throw an exception

return 0;
}