What you are trying to achieve is called type erasure. Take a look at boost::any and it's implementation how it works.
Boost Any
Now to the question, why it does not work. As boost::any demonstrates it is possible to implement. And it works, but your problem would be the dispatching which type is really inside. Contrary to template approach, you will be required to do dispatching at application runtime, since the contained type will be erased. There are 2 possibilities to handle that: Visitor pattern and custom cast implementation (which throws an exception if you are trying to cast to wrong type). In both cases you move compile time type safety to runtime and bypass the compiler's type checks.
Another approach is to introduce the Variant type:
Boost Variant
Variant works differently as boost::any and allows only limited number of types to be stored. This introduces higher type safety, since you really limit the set of expected types. There is a nice article written by Andrey Alexandrescu in ddj, on how to implement such a variant:
Part 1,
Part 2,
Part 3
It's implementation is a bit more complex as that of boost::any, but offer higher type safety and disallows users to put any possible types into the variant, with exception of those being explicitly declared.
As I said it can be implemented in C++, but requires deep knowledge of the language and good interface design, so that users of that class do not handle apples as peaches.
Please remember Henry Spencer's words: If you lie to the compiler, it will get its revenge.
Regards,
Ovanes
Idea of implementation (!untested!)
class any_type
{
class any_container
{
public:
virtual ~any_container(){}
virtual void* pointer()=0;
virtual type_info const& get_type()const=0;
};
template<class T>
class any_container_impl
{
T t_;
public:
any_container_impl(T const& t)
: t_(t)
{}
virtual ~any_container_impl(){}
virtual void* pointer()
{
return &t_;
}
virtual type_info const& get_type()const
{
return typeid(T);
}
};
std::auto_ptr<any_container> content_;
public:
template<class T>
any_type(T const& t)
: content_(new any_container_impl<T>(t))
{}
template<class T>
T* cast_to_ptr()
{
if(typeid(T)!=content_->get_type())
return NULL;
return reinterpret_cast<T*>(content_->pointer());
}
template<class T>
T& cast_to_ref()
{
T* ptr = cast_to_ptr<T>();
if(!ptr)
throw std::logic_error("wrong type");
return *ptr;
}
};