Using functions wrappers to test the class invariant Search for: Wrapping C++ Member Function Calls - Bjarne Stroustrup This code is an application for this function wrapper.
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; }
};
template<class T, class Pref, class Suf>
class Wrap {
T* p;
int* owned;
void incr_owned() const { if (owned) ++*owned; }
void decr_owned() const { if (owned && --*owned == 0) { delete p; delete owned; } }
Pref prefix;
Suf suffix;
public:
Wrap(T& x, Pref pr, Suf su) :p(&x) , owned(0) , prefix(pr) , suffix(su) { }
Wrap(T* pp, Pref pr, Suf su) :p(pp) , owned(new int(1)) , prefix(pr) , suffix(su) { }
Wrap(const Wrap& a)
:p(a.p) , owned(a.owned) , prefix(a.prefix) , suffix(a.suffix) { incr_owned() ; }
Wrap& operator=(const Wrap& a)
{
a.incr_owned() ;
decr_owned() ;
p = a.p;
owned = a.owned;
prefix = a.prefix;
suffix = a.suffix;
return *this;
}
~Wrap() { decr_owned() ; }
Call_proxy<T,Suf> operator->() const { prefix() ; return Call_proxy<T,Suf>(p,suffix) ; }
T* direct() const { return p; } // extract pointer to wrapped object
};
template<class T>
struct Invariant
{
T * m_p;
Invariant(T * p) : m_p(p){}
void operator()() const
{
m_p->Invariant();
}
};
template<class T>
struct TestInvariant : public Wrap<T, Invariant<T>, Invariant<T>>
{
TestInvariant(T &x) : Wrap(x, Invariant<T>(&x), Invariant<T>(&x))
{
}
};
struct X
{
void Invariant()
{
cout << "X::Invariant\n";
}
void F()
{
cout << "X::F\n";
}
};
int main() // test program
{
X x;
TestInvariant<X> wx(x);
wx->F();
return 0;
}