fork download
  1. #include <cassert>
  2. #include <typeinfo>
  3. #include <type_traits>
  4.  
  5. struct const_t
  6. {
  7. typedef void const* ptr_type;
  8. template<class T> struct qualified { typedef const T type; };
  9. };
  10.  
  11. struct nonconst_t : const_t
  12. {
  13. typedef void * ptr_type;
  14. template<class T> struct qualified { typedef T type; };
  15. };
  16.  
  17. template<class Constness = nonconst_t>
  18. class anyptr
  19. {
  20. typedef typename Constness::ptr_type ptr_type;
  21. ptr_type ptr;
  22. std::type_info const* ti;
  23. template<class> friend class anyptr;
  24.  
  25. public:
  26. anyptr()
  27. : ptr(0), ti(0)
  28. {}
  29.  
  30. template<class C>
  31. anyptr(anyptr<C> const& p,
  32. typename std::enable_if<
  33. std::is_convertible<C,Constness>::value
  34. >::type* = 0)
  35. : ptr(p.ptr), ti(p.ti)
  36. {}
  37.  
  38. template<class T>
  39. anyptr(T* p,
  40. typename std::enable_if<
  41. std::is_convertible<T*,ptr_type>::value
  42. >::type* =0)
  43. : ptr(p), ti(&typeid(typename std::remove_const<T>::type))
  44. {}
  45.  
  46. explicit operator bool() const
  47. { return ptr!=0; }
  48.  
  49. std::type_info const& static_type() const
  50. { assert(ti!=0); return *ti; }
  51.  
  52. template<class T>
  53. bool static_type_match() const
  54. { return ti && *ti==typeid(T); }
  55.  
  56. template<class T>
  57. typename Constness::template qualified<T>::type*
  58. get() const {
  59. return static_type_match<T>() ? static_cast<
  60. typename Constness::template qualified<T>::type*
  61. >(ptr) : 0;
  62. }
  63.  
  64. template<class T>
  65. typename Constness::template qualified<T>::type&
  66. deref() const {
  67. if (!static_type_match<T>()) throw std::bad_cast();
  68. return *static_cast<
  69. typename Constness::template qualified<T>::type*
  70. >(ptr);
  71. }
  72. };
  73.  
  74. #include <iostream>
  75. using std::cout;
  76. using std::endl;
  77.  
  78. void check(anyptr<const_t> p)
  79. {
  80. if (!p) {
  81. cout << "p zeigt auf gar nix." << endl;
  82. } else
  83. if (p.static_type_match<int>()) {
  84. cout << "p zeigt auf einen int mit dem Wert " << p.deref<int>() << endl;
  85. } else
  86. if (p.static_type_match<double>()) {
  87. cout << "p zeigt auf einen double mit dem Wert " << p.deref<double>() << endl;
  88. } else {
  89. cout << "p zeigt auf ein Objekt des Typs " << p.static_type().name() << endl;
  90. }
  91. }
  92.  
  93. int main()
  94. {
  95. try {
  96. int i = 23;
  97. double d = 3.1416;
  98. check(&i);
  99. check(&d);
  100. anyptr<> q = &i;
  101. anyptr<const_t> qc = q; // klappt die konvertierung?
  102. cout << "Versuche einen int-Zeiger als double-Zeiger zu dereferenzieren..." << endl;
  103. cout << qc.deref<double>() + 1234.5 << endl;
  104. } catch (std::bad_cast const& x) {
  105. cout << "Upps! Geht doch nicht!" << endl;
  106. }
  107. }
  108.  
Success #stdin #stdout 0s 3064KB
stdin
Standard input is empty
stdout
p zeigt auf einen int mit dem Wert 23
p zeigt auf einen double mit dem Wert 3.1416
Versuche einen int-Zeiger als double-Zeiger zu dereferenzieren...
Upps! Geht doch nicht!