fork download
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. template<typename T>
  5. using require_scalar = typename std::enable_if<std::is_arithmetic<T>::value>::type;
  6.  
  7. template<typename T>
  8. using require_not_scalar = typename std::enable_if<not std::is_arithmetic<T>::value>::type;
  9.  
  10. class any_ptr
  11. {
  12. struct WrapperBase
  13. {
  14. virtual ~WrapperBase(){}
  15. };
  16.  
  17. template< typename T >
  18. struct Wrapper : WrapperBase, T
  19. {
  20. template<typename ... Args>
  21. Wrapper( Args&&... args ):
  22. T( std::forward<Args>(args)... ) {}
  23. };
  24.  
  25. template< typename T >
  26. struct ScalarWrapper : WrapperBase
  27. {
  28. T scalar;
  29.  
  30. template<typename ... Args>
  31. ScalarWrapper( Args&&... args ):
  32. scalar( std::forward<Args>(args)... ) {}
  33. };
  34.  
  35. std::unique_ptr<WrapperBase> mPtr;
  36.  
  37. any_ptr( std::unique_ptr<WrapperBase> ptr ):
  38. mPtr{ std::move(ptr) } {}
  39.  
  40. template< typename T >
  41. T* _access( std::false_type ) const
  42. {
  43. return dynamic_cast<T*>(mPtr.get());
  44. }
  45.  
  46. template< typename T >
  47. T* _access( std::true_type ) const
  48. {
  49. auto ptr = dynamic_cast<ScalarWrapper<T>*>(mPtr.get());
  50. return ptr ? &ptr->scalar : nullptr ;
  51. }
  52.  
  53. template< typename T,
  54. typename ... Args >
  55. static any_ptr _make_any_ptr( std::false_type, Args&&... args )
  56. {
  57. return std::unique_ptr<WrapperBase>{ new Wrapper<T>{ std::forward<Args>(args)... } };
  58. }
  59.  
  60. template< typename T >
  61. static any_ptr _make_any_ptr( std::true_type, T arg )
  62. {
  63. return std::unique_ptr<WrapperBase>{ new ScalarWrapper<T>{arg} };
  64. }
  65.  
  66. public:
  67.  
  68. template< typename T >
  69. T* access()
  70. { return _access<T>( typename std::is_arithmetic<T>::type{} ); }
  71.  
  72. template< typename T >
  73. T const* access() const
  74. { return _access<T>( typename std::is_arithmetic<T>::type{} ); }
  75.  
  76. template< typename T,
  77. typename ... Args >
  78. friend any_ptr make_any_ptr( Args&&... args )
  79. {
  80. return _make_any_ptr<T>( typename std::is_arithmetic<T>::type{}, std::forward<Args>(args)... );
  81. }
  82. };
  83.  
  84. ////////////////////////////////////////////////////////////////////////////////
  85.  
  86. template <class T>
  87. void inspect(any_ptr& p, void (&fun)(T))
  88. {
  89. using actual_t = typename std::remove_reference<T>::type;
  90.  
  91. if( auto t = p.access<actual_t>() )
  92. fun(*t);
  93. }
  94.  
  95. ////////////////////////////////////////////////////////////////////////////////
  96.  
  97. class printable
  98. {
  99. public:
  100. virtual void print() const = 0;
  101. };
  102.  
  103. ////////////////////////////////////////////////////////////////////////////////
  104.  
  105. #include <string>
  106. using namespace std;
  107.  
  108. class foo : public printable
  109. {
  110. public:
  111. foo(string const& s) : m_s(s) {}
  112.  
  113. virtual void print() const
  114. {
  115. cout << "foo: " << m_s << "\n";
  116. }
  117.  
  118. private:
  119. string m_s;
  120. };
  121.  
  122. class bar : public printable
  123. {
  124. public:
  125. bar(int i) : m_i(i) {}
  126.  
  127. virtual void print() const
  128. {
  129. cout << "bar: " << m_i << "\n";
  130. }
  131.  
  132. private:
  133. int m_i;
  134. };
  135.  
  136. ////////////////////////////////////////////////////////////////////////////////
  137.  
  138. void print_printable(printable& p)
  139. {
  140. p.print();
  141. }
  142.  
  143. ////////////////////////////////////////////////////////////////////////////////
  144.  
  145. int main()
  146. {
  147. auto f = make_any_ptr<foo>("foo");
  148. auto b = make_any_ptr<bar>(42);
  149. auto c = make_any_ptr<int>(42);
  150.  
  151. inspect(f, print_printable);
  152. inspect(b, print_printable);
  153.  
  154. auto ptr = c.access<int>();
  155. std::cout << *ptr;
  156. }
  157.  
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
foo: foo
bar: 42
42