Wrapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
Wrapping C++ Member Function Calls
----Bjarne Stroustrup
Published in the June 2000 issue of "The C++ Report".
*/


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; }
    /* !!! this can work because: aWrap->f() <===> aWrap.operator->()->f() <===> aWrap.operator->().operator->()->f() */
};

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
    Wrap &self() { return *this; }// to enable recursive wrapper.
};

#include<iostream>
using namespace std;
void prefix() { cout << "prefix "; }
void suffix() { cout << " suffix\n"; }
class X{ // one user class
public:
    X() { cout << "make an X\n"; }
    ~X(){ cout << "destroy an X\n"; }
    int f() const { cout << "f()"; return 1; }
    void g() const { cout << "g()"; }
};
class Y{ // another user class
public:
    Y() { cout << "make a Y\n"; }
    ~Y() { cout << "destroy a Y\n"; }
    void h() const { cout << "h()"; }
};
struct Pref { void operator()() const { cout << "Pref "; } };
struct Suf { void operator()() const { cout << " Suf\n"; } };

#if 0

/* 7 Parameterization, lock example */
struct Lock {
    sys_lock lck;
    Lock(sys_lock &x): lck(x) {}
    void operator()() const { grab(lck); }
};
struct Unlock{
    sys_lock lck;
    Unlock(sys_lock &x): lck(x) {}
    void operator()() const { release(lck); }
};
Wrap<X, Lock, Unlock> x3(x, Lock(screen_lock), Unlock(screen_lock));
Wrap<X, Lock, Unlock> x4(y, Lock(lock3a), Unlock(lock3a));

/* 8 Notational Convenience */
template<class T>
class Shared: public Wrap<T, Lock, Unlock>
{
public:
    Shared(T &obj, sys_lock &lck): Wrap<T, Lock, Unlock>(obj, Lock(lck), Unlock(lck)) {}
    Shared(T *ptr, sys_lock &lck): Wrap<T, Lock, Unlock>(ptr, Lock(lck), Unlock(lck)) {}
};
Shared<X> x3(x, screen_lock);
Shared<X> x4(y, lock3);

template<class T>
struct Tracer: public Wrap<T, void(*)(), void(*)()> {
    Tracer(T &x): Wrap<T, void(*)(), void(*)()>(x, trace_on, trace_off) {}
};
X x;
Tracer<X> xx(x);
typedef Tracer<X> Xtracer;
Xtracer xxx(x);

#endif

int main() {
    Wrap<X, void(*)(), void(*)()> xx(new X, prefix, suffix);
    Wrap<Y, void(*)(), void(*)()> yy(new Y, prefix, suffix);
    Wrap<X, void(*)(), void(*)()> x2 = xx;

    X x;
    Wrap<X, Pref, Suf> x3(x, Pref(), Suf());

    if(xx->f()) cout<<"done\n";

    xx->g();
    x2->g();
    xx=x2;
    x2->g();
    x3->g();
    yy->h();

    // recurisive wrapper:
    cout << "!!!\n";
    Wrap<Wrap<X, void(*)(), void(*)()>, Pref, Suf> ww(new Wrap<X, void(*)(), void(*)()>(new X, prefix, suffix), Pref(), Suf());
    ww->operator->()->g(); // tasteless, but it works.
    ww->self()->f(); // using self() function.
    cout << "!!!\n";

    return 0;
}

One Comment

  • jb说道:

    Is there some way to post blog code in a sane way? The lack of formatting makes reading anything but HelloWorld a pain to read 🙁