fork download
  1. #include <iostream>
  2. #include <memory>
  3. #include <typeindex>
  4.  
  5. class any_ptr
  6. {
  7. struct WrapperBase
  8. {
  9. virtual ~WrapperBase(){}
  10. };
  11.  
  12. template< typename T >
  13. struct Wrapper : WrapperBase, T
  14. {
  15. template<typename ... Args>
  16. Wrapper( Args&&... args ):
  17. T( std::forward<Args>(args)... ) {}
  18. };
  19.  
  20. struct PointerBase : WrapperBase
  21. {
  22. std::type_index typeIndex;
  23.  
  24. PointerBase( std::type_index ti ):
  25. typeIndex{ti} {}
  26. };
  27.  
  28. template< typename T >
  29. struct ScalarWrapper : WrapperBase
  30. {
  31. T scalar;
  32.  
  33. template<typename Arg>
  34. ScalarWrapper( Arg&& arg ):
  35. scalar( std::forward<Arg>(arg) ) {}
  36. };
  37.  
  38. std::unique_ptr<WrapperBase> mPtr;
  39.  
  40. any_ptr( std::unique_ptr<WrapperBase> ptr ):
  41. mPtr{ std::move(ptr) } {}
  42.  
  43. template< typename T >
  44. T* _access( std::false_type, std::false_type ) const
  45. {
  46. return dynamic_cast<T*>(mPtr.get());
  47. }
  48.  
  49. template< typename T >
  50. T* _access( std::true_type, std::false_type ) const
  51. {
  52. auto ptr = dynamic_cast<ScalarWrapper<T>*>(mPtr.get());
  53. return ptr ? &ptr->scalar : nullptr ;
  54. }
  55.  
  56. template< typename T >
  57. T* _access( std::true_type, std::true_type ) const
  58. {
  59. using pointee = typename std::remove_pointer<T>::type;
  60.  
  61. auto ptr = dynamic_cast<PointerBase*>(mPtr.get());
  62.  
  63. if( ptr
  64. && ptr->typeIndex <= typeid(pointee) ) // Dieser Typ ist eine Basisklasse oder ein größerer Skalar o.ä.
  65. return &static_cast<ScalarWrapper<T>*>(dynamic_cast<void*>(ptr))->scalar;
  66.  
  67. return _access<T>( std::true_type{}, std::false_type{} );
  68. }
  69.  
  70. template< typename T,
  71. typename ... Args >
  72. static any_ptr _make_any_ptr( std::false_type, Args&&... args )
  73. {
  74. return std::unique_ptr<WrapperBase>{ new Wrapper<T>{ std::forward<Args>(args)... } };
  75. }
  76.  
  77. template< typename T >
  78. static any_ptr _make_any_ptr( std::true_type, T arg )
  79. {
  80. return std::unique_ptr<WrapperBase>{ new ScalarWrapper<T>{arg} };
  81. }
  82.  
  83. public:
  84.  
  85. template< typename T >
  86. T* access()
  87. { return _access<T>( typename std::is_scalar<T>::type{}, typename std::is_pointer<T>::type{} ); }
  88.  
  89. template< typename T >
  90. T const* access() const
  91. { return const_cast<any_ptr*>(this)->access<T>(); }
  92.  
  93. template< typename T,
  94. typename ... Args >
  95. friend any_ptr make_any_ptr( Args&&... args )
  96. {
  97. return _make_any_ptr<T>( typename std::is_scalar<T>::type{}, std::forward<Args>(args)... );
  98. }
  99. };
  100.  
  101. template< typename T >
  102. struct any_ptr::ScalarWrapper<T*> : any_ptr::PointerBase
  103. {
  104. T* scalar;
  105.  
  106. template<typename Arg>
  107. ScalarWrapper( Arg&& arg ):
  108. PointerBase{ typeid(T) },
  109. scalar( std::forward<Arg>(arg) ) {}
  110. };
  111.  
  112. ////////////////////////////////////////////////////////////////////////////////
  113.  
  114. template <class T>
  115. void inspect(any_ptr& p, void (&fun)(T))
  116. {
  117. using actual_t = typename std::remove_reference<T>::type;
  118.  
  119. if( auto t = p.access<actual_t>() )
  120. fun(*t);
  121. }
  122.  
  123. ////////////////////////////////////////////////////////////////////////////////
  124.  
  125. class printable
  126. {
  127. public:
  128. virtual void print() const = 0;
  129. };
  130.  
  131. ////////////////////////////////////////////////////////////////////////////////
  132.  
  133. #include <string>
  134. using namespace std;
  135.  
  136. class foo : public printable
  137. {
  138. public:
  139. foo(string const& s) : m_s(s) {}
  140.  
  141. virtual void print() const
  142. {
  143. cout << "foo: " << m_s << "\n";
  144. }
  145.  
  146. private:
  147. string m_s;
  148. };
  149.  
  150. class bar : public printable
  151. {
  152. public:
  153. bar(int i) : m_i(i) {}
  154.  
  155. virtual void print() const
  156. {
  157. cout << "bar: " << m_i << "\n";
  158. }
  159.  
  160. private:
  161. int m_i;
  162. };
  163.  
  164. ////////////////////////////////////////////////////////////////////////////////
  165.  
  166. void print_printable(printable& p)
  167. {
  168. p.print();
  169. }
  170.  
  171. ////////////////////////////////////////////////////////////////////////////////
  172.  
  173. int main()
  174. {
  175. bar b = 42;
  176. auto any = make_any_ptr<bar*>(&b);
  177.  
  178. auto b_ptr = any.access<printable*>();
  179.  
  180. if( b_ptr )
  181. (*b_ptr)->print();
  182.  
  183. short i = 42;
  184. auto any2 = make_any_ptr<short*>(&i);
  185.  
  186. auto i_ptr = any2.access<int*>();
  187.  
  188. if( i_ptr )
  189. std::cout << **i_ptr;
  190. }
  191.  
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
bar: 42