// Paolo Medici 
// University of Parma

#include <typeinfo>
/// A minimalistic boost::any free implementation without virtual function.
/// It do not have `clone' virtual function then a `shared pointer' technique is 
///  used. Object destructor are not called, then this class should be used only 
///  for destructorless types.
/// Object size produced by this implementation should be lesser then boost::any
/// In this example myanycast executable is 6228 bytes, anycast 7716 bytes.
class any_type {
  struct value_type {
	const std::type_info * m_type;
	int m_ref_count;
	value_type(const std::type_info *type) : m_type(type), m_ref_count(1) { }
 };

 template<typename T>
 struct impl_value_type: public value_type {
    T m_data;
    impl_value_type(const T & data) : value_type(&typeid(T)), m_data(data) { }
  };
 
 value_type *value;

 void release()
 {
 if(value)
	{
	value->m_ref_count--;
	if(value->m_ref_count == 0)
		delete value;	// WW not typesafe, and object destructor are not called.
	}
 }

 
 public:
 any_type() : value(0) { }
 any_type(const any_type & src) 
  { 
  src.value->m_ref_count++;
  value = src.value;
  } 
 ~any_type() 
 {
 
 release();
 }
 template<class T>
 explicit any_type(const T & data)  : value(0) { assign(data); }

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

 void operator = (const any_type & src)
 {
  src.value->m_ref_count++;
  release();
  value = src.value;
 }

 template<class T>
 operator T () const { return get<T>(); }
	
 template<class T>
 void assign (const T & data)
	{
	release();
	value = new impl_value_type<T>(data);
	}

 template<class T>
 T & get() const
	{
	if( *value->m_type == typeid(T) )
		return static_cast<impl_value_type<T> *>(value)->m_data;
	else
		{
		throw std::bad_cast();	
		}
	}

};

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

#include <vector>
#include <iostream>

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

int main()
{
std::vector<any_type> a;

a.push_back(any_type(1));
a.push_back(any_type(1.0));

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

return 0;
}