File: structure.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 (77 lines) | stat: -rw-r--r-- 2,973 bytes parent folder | download | duplicates (4)
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
Policy classes usually define behavior, not structure. Policy classes
        hi(policy class: defining structure)
 are normally used to parameterize some aspect of the behavior of classes that
are derived from them. However, different policies may require different data
members. These data members may also be defined by the policy classes. Policy
classes may therefore be used to define both behavior and structure.

By providing a well-defined interface a class derived from a policy class may
define member specializations using the different structures of policy classes
to their advantage. For example, a plain pointer-based policy class could
offer its functionality by resorting to bf(C)-style i(pointer juggling),
whereas a tt(vector)-based policy class could use the vector's members
directly.

In this example a generic class template tt(Size) could be designed
expecting a container-like policy using features commonly found in
containers, defining the data (and hence the structure) of the container
specified in the policy. E.g.:
        verb(
    template <typename Data, template <typename> class Container>
    struct Size: public Container<Data>
    {
        size_t size()
        {                           // relies on the container's `size()'
                                    // note: can't use `this->size()'
            return Container<Data>::size();
        }
    };
        )
    A specialization can now be defined for a much simpler storage class
using, e.g., plain pointers (the implementation capitalizes on tt(first) and
tt(second), data members of tt(std::pair).  Cf. the example at the end of this
section):
        verb(
    template <typename Data>
    struct Size<Data, Plain>: public Plain<Data>
    {
        size_t size()
        {                           // relies on pointer data members
            return this->second - this->first;
        }
    };
        )
    Depending on the intentions of the template's author other members could
be implemented as well.

    To simplify the real use of the above templates, a generic wrapper class
can be constructed: it uses the tt(Size) template matching the actually used
storage type (e.g., a tt(std::vector) or some plain storage class) to define
its structure:
        verb(
    template <typename Data, template <typename> class Store>
    class Wrapper: public Size<Data, Store>
    {};
        )

    The above classes could now be used as follows (em(en passant) showing an
extremely basic tt(Plain) class):
        verb(
    #include <iostream>
    #include <vector>

    template <typename Data>
    struct Plain: public std::pair<Data *, Data *>
    {};

    int main()
    {
        Wrapper<int, std::vector> wiv;
        std::cout << wiv.size() << "\n";

        Wrapper<int, Plain> wis;
        std::cout << wis.size() << "\n";
    }
        )
    The tt(wiv) object now defines vector-data, the tt(wis) object merely
defines a tt(std::pair) object's data members.