File: implement.yo

package info (click to toggle)
c%2B%2B-annotations 10.6.0-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 10,536 kB
  • ctags: 3,247
  • sloc: cpp: 19,157; makefile: 1,521; ansic: 165; sh: 128; perl: 90
file content (260 lines) | stat: -rw-r--r-- 8,751 bytes parent folder | download | duplicates (3)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
itemization(
    it() First, the necessary class interfaces are defined. The existence
        of a class tt(Date) is assumed, containing overloaded operators
        like tt(<) and tt(>) to compare dates.
        To start with, we present the interface of the class
        tt(Person), omitting all the standard stuff like overloaded assignment
        operator, (copy) constructors, etc.:
        verb(
#include <cstdlib>     // for qsort()

class Date;

class Person
{
    public:
        size_t length() const;
        size_t mass() const;
        char const *name() const;
        char const *city() const;
        Date const &birthdate() const;

    private:
        // all necessary data members
};
        )
    it() Next, the class tt(Person_dbase).
        Within this class a tt(struct CmpPerson) is defined, containing
        two fields:
        itemization(
            it() A pointer to a union of compare functions.

                As the compare functions are static functions of the class
                tt(Person_dbase), pointers to these functions are
                indiscernible from pointers to functions at the global
                (tt(::)) level. The compare functions return tt(int)s (for
                tt(qsort())), and expect two pointers to tt(Person const)
                objects. The field tt(persons) expects the two pointers to
                tt(Person const) objects. The field tt(voids) is the alternate
                interpretation, to be used with tt(qsort()), instead of the
                typecast tt((pif2vp)).

            it() A field tt(pf) (pointer to access function) of
                the nested tt(union Person_accessor).

                The types of as many different access functions of the
                tt(Person) class as are used in the class are declared in this
                union.

                Access functions returning tt(int)s, tt(char const *)s and
                tt(Date &)s are needed. Consequently, the tt(Person_accessor)
                union contains these (three) types.
        )

        From this tt(CmpPerson) struct a static array tt(cmpPerson[]) is
        constructed. It is a tt(static Person_dbase) array, making it possible
        for the compare functions to inspect its elements+footnote( The number
        of elements of the tt(cmpPerson[]) array is not specified in the
        interface: that number is determined at compile-time by the compiler,
        when the static variable tt(cmpPerson[]) is initialized.).

        Also note the tt(static Listtype selector). This variable
        is used by the compare functions to find the actual
        tt(Person) access function to be used.
        Here, then, is the interface of the class tt(Person_dbase):
            verb(
class Person_dbase
{
    public:
        enum Listtype
        {
            list_by_length,
            list_by_mass,
            list_by_name,
            list_by_city,
            list_by_birthday,
        };

        // ... constructors etc.

        void list(Listtype type);
                    // list the information
    private:
        struct CmpPerson
        {
            union Compare_function
            {
                int (*persons)// comparing two Persons
                    (Person const *p1, Person const *p2);
                int (*voids)// for qsort()
                    (void const *p1, void const *p2);
            }
                cmp;

            union Person_accessor
            {
                char const
                    *(Person::*cp)() const;
                int
                    (Person::*i)() const;
                Date const
                    &(Person::*d)() const;
            }
                pf;     // to Person's access functions
        };

        static CmpPerson
            cmpPerson[];
        static Listtype
            selector;

        static int cmpstr(Person const *p1,
                          Person const *p2);

        static int cmpint(Person const *p1,
                          Person const *p2);

        static int cmpdate(Person const *p1,
                          Person const *p2);

        Person
            *pp;    // pointer to the info
        size_t
            n;      // number of persons stored.
};
        )
    Next, we define each of the members of the tt(Person_dbase) class
    (as far as necessary).

    it() The tt(list()) function now only has to do three things:
        itemization(
            it() The tt(Listtype) parameter is copied to
                tt(selector),
            it() The function tt(qsort()) is called. Note the
                use of the tt(cmpPerson) array to determine which compare
                function to use.
            it() The information of the tt(Person)objects is
                displayed. This part is left for the reader to implement.
        )
            verb(
    void Person_dbase::list(Listtype type)
    {
        selector = type;
        qsort(pp, n, sizeof(Person), cmpPerson[type].cmp.voids);
        // list the sorted Person-database (to be implemented)
    }
            )
    it() The array tt(cmpPerson[]) is a static array of tt(CmpPerson)
        elements. In this example there are five different ways to sort
        the data. Consequently, there are five elements in the array
        tt(cmpPerson[]). All these elements can be defined and initialized
        by the compiler. No run-time execution time is needed for this.

        However, note the form of the declaration: the array is defined in
        the scope of the tt(Person_dbase) class. Its elements are
        tt(CmpPerson)s, also defined in the scope of the tt(Person_dbase)
        class. Hence the double mentioning of tt(Person_dbase).
            verb(
Person_dbase::CmpPerson
    Person_dbase::cmpPerson[] =
    {
        {       // compare- and access
                // function to compare length
            cmpint,
            Person::length,
        },

        {       // same for mass
            cmpint,
            Person::mass,
        },

        {       // same for name
            cmpstr,
            Person::name,
        },

        {       // same for city
            cmpstr,
            Person::city,
        },

        {       // same for Date
            cmpdate,
            Person::birthdate,
        },
    };
            )
    it() Now only the compare functions remain to be implemented. Although
        five accessors can be used, only three compare functions are needed.

        The compare functions, being static functions, have access to the
        tt(cmpPerson[]) array and to the tt(Listtype selector) variable. This
        information is used by the compare functions to call the relevant
        access member function
        of the two tt(Person) objects, pointed to by the parameters of the
        compare functions.

        For this, the tt(pointer to member) operator
        tt(->*) is used. The element tt(cmpPerson[selector])
        contains the function pointers to the functions to be used:
        they are the fields
        tt(pf), variant tt(cp, i) or tt(d). These fields
        return a pointer to a particular access function of a tt(Person)
        object.

        Through these pointers the functions can be associated to a
        particular tt(Person)
        object using the pointer to member operator. This results in
        expressions like:
        center(tt(p1->*cmpPerson[selector].pf.cp))

        By this time we have
        the name (i.e., address) of an access function for a particular
        tt(Person) object. To call this function, parentheses are needed,
        one set of parentheses to protect this expression from
        desintegrating due to the
        high priority of the second set of parentheses, which are
        needed for the actual call of the function. Hence, we get:
        center(tt((p1->*cmpPerson[selector].pf.cp)()))

        Finally, here are the three compare functions:
            verb(
int Person_dbase::cmpstr(Person const *p1, Person const *p2)
{
    return
    (
        strcmp
        (
            (p1->*cmpPerson[selector].pf.cp)(),
            (p2->*cmpPerson[selector].pf.cp)()
        )
    );
}

int Person_dbase::cmpint(Person const *p1, Person const *p2)
{
    return
    (
        (p1->*cmpPerson[selector].pf.i)()
        -
        (p2->*cmpPerson[selector].pf.i)()
    );
}

int Person_dbase::cmpdate(Person const *p1, Person const *p2)
{
    return
    (
        (p1->*cmpPerson[selector].pf.d)()
        <
        (p2->*cmpPerson[selector].pf.d)() ?
            -1
        :
            (p1->*cmpPerson[selector].pf.d)()
            >
            (p2->*cmpPerson[selector].pf.d)()
    );
}
            )
)