fork download
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. using namespace std;
  5.  
  6. template< typename T, typename TProlog, typename TEpilog ,
  7. bool call_epilog_due_to_prolog_exeption=true>
  8. class decorator
  9. {
  10. TProlog prolog;
  11. struct TDeleter
  12. {
  13. std::shared_ptr<T> ptr;
  14. TEpilog epilog;
  15. void operator() (T*p)
  16. {
  17. // assert( p == ptr.get() )
  18. epilog();
  19. }
  20. } deleter;
  21.  
  22. public:
  23. decorator(std::shared_ptr<T> ptr, TProlog prolog, TEpilog epilog)
  24. : prolog(prolog), deleter({ptr, epilog })
  25. {}
  26. decorator(const decorator&) = default;
  27. decorator(decorator&&) = default;
  28.  
  29. std::shared_ptr<T> operator->() const
  30. {
  31. return get();
  32. }
  33.  
  34. std::shared_ptr<T> get() const
  35. {
  36. if(call_epilog_due_to_prolog_exeption)
  37. {
  38. std::shared_ptr<T> result( deleter.ptr.get(), deleter );
  39. prolog();
  40. return result;
  41. }
  42. else
  43. {
  44. prolog();
  45. std::shared_ptr<T> result( deleter.ptr.get(), deleter );
  46. return result;
  47. }
  48. }
  49. };
  50.  
  51. template< typename T, typename TProlog, typename TEpilog >
  52. decorator<T,TProlog,TEpilog>
  53. decorate_ptr(std::shared_ptr<T> ptr, TProlog prolog, TEpilog epilog)
  54. {
  55. return decorator<T,TProlog,TEpilog>(ptr, prolog, epilog);
  56. }
  57.  
  58. template< typename T, typename TProlog, typename TEpilog >
  59. decorator<T,TProlog,TEpilog>
  60. decorate_obj(T& obj, TProlog prolog, TEpilog epilog)
  61. {
  62. std::shared_ptr<T> ptr( &obj, [](void*){} ); // no call 'delete'
  63. return decorator<T,TProlog,TEpilog>(ptr, prolog, epilog);
  64. }
  65.  
  66.  
  67.  
  68. class FooTest
  69. {
  70. public:
  71. void foo()
  72. {
  73. std::cout << "foo()" << std::endl;
  74. }
  75. } foo_test;
  76.  
  77.  
  78. int main()
  79. {
  80. auto foo_ptr = decorate_obj(foo_test,
  81. [](){ std::cout<<"prolog()"<<std::endl; } ,
  82. [](){ std::cout<<"epilog()"<<std::endl; } );
  83. foo_ptr->foo();
  84.  
  85. return 0;
  86. }
  87.  
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
prolog()
foo()
epilog()