fork download
  1. #include <iostream>
  2. #include <memory>
  3. #include <utility>
  4. #include <type_traits>
  5. using namespace std;
  6.  
  7. template <typename T>
  8. class has_operator
  9. {
  10. typedef char yes;
  11. typedef char no[2];
  12. template <typename I> static I identity(I);
  13.  
  14. template<typename U,U> struct Check;
  15. template <typename C> static yes& test(Check<decltype(identity(&C::operator->)),&C::operator-> >*);
  16. template <typename C> static no& test(...);
  17.  
  18. public:
  19. enum { value = sizeof(test<T>(0)) == sizeof(yes) };
  20. };
  21.  
  22.  
  23. template<class T, bool hasOperator = has_operator<T>::value>
  24. struct PtrOperator {
  25. T* p;
  26. PtrOperator(T*pp) : p(pp) {}
  27. T* operator->() const { return p;}
  28. };
  29.  
  30. template<class T>
  31. struct PtrOperator<T,true>{
  32. T* p;
  33. PtrOperator<T,true>(T*pp) : p(pp) {}
  34. T& operator->() const { return *p;}
  35. };
  36.  
  37. template<class T, class Pref, class Suf> class Wrap;
  38. template<class T, class Suf>
  39. class Call_proxy : public PtrOperator<T>{
  40. mutable bool own;
  41. Suf suffix;
  42. Call_proxy(T* pp, Suf su) : PtrOperator<T>(pp) , own(true) , suffix(su) { } // restrict creation
  43. Call_proxy& operator=(const Call_proxy&) ; // prevent assignment
  44. public:
  45. template<class U, class P, class S> friend class Wrap;
  46. Call_proxy(const Call_proxy& a) : PtrOperator<T>(a.p) , own(true) , suffix(a.suffix) { a.own=false; }
  47. ~Call_proxy() { if (own) suffix() ; }
  48. };
  49.  
  50. template<class T, class Pref, class Suf>
  51. class Wrap {
  52. T& p;
  53. Pref prefix;
  54. Suf suffix;
  55. public:
  56. Wrap(T& x, Pref pr, Suf su) :p(x) , prefix(pr) , suffix(su) { }
  57. Call_proxy<T,Suf> operator->() const{ prefix() ; return Call_proxy<T,Suf>(&p,suffix) ; }
  58. };
  59.  
  60. class X { // one user class
  61. public:
  62. X() { cout << " make an X\n"; }
  63. ~X() { cout << "destroy an X\n"; }
  64. int f() const{ cout << "f()"; return 1; }
  65. void g() const{ cout << "g()"; }
  66.  
  67. //X* operator->(){return this;}
  68. };
  69.  
  70. void prefix() { cout << "prefix "; }
  71. void suffix() { cout << " suffix\n"; }
  72.  
  73. struct Pref { void operator()() const{ cout<< " Pref "; } };
  74. struct Suf { void operator()() const{ cout<< " Suf "; } };
  75.  
  76. template<class T>
  77. struct Shared : public Wrap<T,Pref, Suf>
  78. {
  79. using Wrap<T,Pref,Suf>::operator->;
  80. Shared(T& obj) : Wrap<T,Pref, Suf>(obj,Pref() , Suf()) { }
  81. };
  82.  
  83. template<class T>
  84. struct Tracer : public Wrap<T,void(*)() ,void(*)()> {
  85. using Wrap<T,void(*)() ,void(*)()>::operator->;
  86. Tracer(T& x) : Wrap<T,void(*)() ,void(*)()>(x,::prefix,::suffix) { }
  87. };
  88.  
  89.  
  90.  
  91. template<class T> struct Sealed {
  92. T&p;
  93. Sealed(T&x ) : p(x){}
  94. T* operator->() {return &p;}
  95. };
  96.  
  97. int main() // test program
  98. {
  99. X x;
  100. Sealed<X> xx(x);
  101. Shared<Sealed<X>> xxx(xx) ;
  102. Tracer<Shared<Sealed<X>>> xxxx(xxx);
  103.  
  104. auto y = std::make_shared<X>();
  105. Shared<decltype(y)> yy(y);
  106. Tracer<decltype(yy)>yyy(yy);
  107.  
  108. xx->g();
  109. xxx->g();
  110. xxxx->g();
  111.  
  112. y->g();
  113. yy->g();
  114. yyy->g();
  115.  
  116. std::cout << has_operator<X>::value << std:: endl;
  117. std::cout << has_operator<Shared<X>>::value << std:: endl;
  118. std::cout << has_operator<Tracer<Shared<X>>>::value << std:: endl;
  119.  
  120. Shared<X> z(x) ;
  121. Tracer<Shared<X>> zz(z);
  122.  
  123. x.g();
  124. z->g();
  125. zz->g();
  126.  
  127. return 0;
  128. }
Success #stdin #stdout 0s 3480KB
stdin
Standard input is empty
stdout
 make an  X
 make an  X
g() Pref g() Suf prefix  Pref g() Suf  suffix
g() Pref g() Suf prefix  Pref g() Suf  suffix
0
1
1
g() Pref g() Suf prefix  Pref g() Suf  suffix
destroy an  X
destroy an  X