#include <cassert>
#include <typeinfo>
#include <type_traits>
struct const_t
{
typedef void const* ptr_type;
template<class T> struct qualified { typedef const T type; };
};
struct nonconst_t : const_t
{
typedef void * ptr_type;
template<class T> struct qualified { typedef T type; };
};
template<class Constness = nonconst_t>
class anyptr
{
typedef typename Constness::ptr_type ptr_type;
ptr_type ptr;
std::type_info const* ti;
template<class> friend class anyptr;
public:
anyptr()
: ptr(0), ti(0)
{}
template<class C>
anyptr(anyptr<C> const& p,
typename std::enable_if<
std::is_convertible<C,Constness>::value
>::type* = 0)
: ptr(p.ptr), ti(p.ti)
{}
template<class T>
anyptr(T* p,
typename std::enable_if<
std::is_convertible<T*,ptr_type>::value
>::type* =0)
: ptr(p), ti(&typeid(typename std::remove_const<T>::type))
{}
explicit operator bool() const
{ return ptr!=0; }
std::type_info const& static_type() const
{ assert(ti!=0); return *ti; }
template<class T>
bool static_type_match() const
{ return ti && *ti==typeid(T); }
template<class T>
typename Constness::template qualified<T>::type*
get() const {
return static_type_match<T>() ? static_cast<
typename Constness::template qualified<T>::type*
>(ptr) : 0;
}
template<class T>
typename Constness::template qualified<T>::type&
deref() const {
if (!static_type_match<T>()) throw std::bad_cast();
return *static_cast<
typename Constness::template qualified<T>::type*
>(ptr);
}
};
#include <iostream>
using std::cout;
using std::endl;
void check(anyptr<const_t> p)
{
if (!p) {
cout << "p zeigt auf gar nix." << endl;
} else
if (p.static_type_match<int>()) {
cout << "p zeigt auf einen int mit dem Wert " << p.deref<int>() << endl;
} else
if (p.static_type_match<double>()) {
cout << "p zeigt auf einen double mit dem Wert " << p.deref<double>() << endl;
} else {
cout << "p zeigt auf ein Objekt des Typs " << p.static_type().name() << endl;
}
}
int main()
{
try {
int i = 23;
double d = 3.1416;
check(&i);
check(&d);
anyptr<> q = &i;
anyptr<const_t> qc = q; // klappt die konvertierung?
cout << "Versuche einen int-Zeiger als double-Zeiger zu dereferenzieren..." << endl;
cout << qc.deref<double>() + 1234.5 << endl;
} catch (std::bad_cast const& x) {
cout << "Upps! Geht doch nicht!" << endl;
}
}