I've found this paper implementing a C++ proxy wrapper class, which allows Code execution before and after each method call by overloading operator->
.
In Section 11, Techniques it is mentioned that it is possible to chain wrapper classes into each other, like
#include <iostream>
using namespace std;
template<class T, class Pref, class Suf> class Wrap;
template<class T, class Suf>
class Call_proxy {
T* p;
mutable bool own;
Suf suffix;
Call_proxy(T* pp, Suf su) :p(pp) , own(true) , suffix(su) { } // restrict creation
Call_proxy& operator=(const Call_proxy&) ; // prevent assignment
public:
template<class U, class P, class S> friend class Wrap;
Call_proxy(const Call_proxy& a) : p(a.p) , own(true) , suffix(a.suffix) { a.own=false; }
~Call_proxy() { if (own) suffix() ; }
T* operator->() const{ return p;} // error: ‘struct Shared<X>’ has no member named ‘g’
//T& operator->() const{ return *p;} // error: result of ‘operator->()’ yields non-pointer result
};
template<class T, class Pref, class Suf>
class Wrap {
T& p;
Pref prefix;
Suf suffix;
public:
Wrap(T& x, Pref pr, Suf su) :p(x) , prefix(pr) , suffix(su) { }
Call_proxy<T,Suf> operator->() const{
prefix() ;
return Call_proxy<T,Suf>(&p,suffix);
}
};
void prefix() { cout << "prefix "; }
void suffix() { cout << " suffix\n"; }
struct Pref { void operator()() const{ cout<< " Pref "; } };
struct Suf { void operator()() const{ cout<< " Suf "; } };
template<class T> struct Shared : public Wrap<T,Pref, Suf> {
Shared(T& obj) : Wrap<T,Pref, Suf>(obj,Pref() , Suf()) { }
};
template<class T> struct Tracer : public Wrap<T,void(*)() ,void(*)()> {
Tracer(T& x) : Wrap<T,void(*)() ,void(*)()>(x,::prefix,::suffix) { }
};
class X {
public:
void g() const{ cout << "g()"; }
};
int main() {// test program
X x;
Shared<X> xx(x) ;
Tracer<Shared<X>> xxx(xx);
xx->g();
xxx->g();
return 0;
}
But this fails with the error error: ‘struct Shared<X>’ has no member named ‘g’
.
I read about operator->
overloading and understand the problem (Call_proxy
returns a pointer, which does not propagate the overloading, as mentioned here).
I tried some alternatives by returning reference instead of pointer, but in the end I have either the problem mentioned above, or the problem that operator->
is called on a reference type (error: result of ‘operator->()’ yields non-pointer result
).
Is there a way to achieve this? As it was mentioned in the paper, I thought it should be possible.
Edit: Code versions for both errors.
- http://ideone.com/ff9UyN (
error: ‘struct Shared<X>’ has no member named ‘g’
. I read aboutoperator->
) - http://ideone.com/CV93qX (
error: result of ‘operator->()’ yields non-pointer result
)
Both versions are the same, with line 17 or line 18 commented out.