File: memberfunctionadaptors.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 (109 lines) | stat: -rw-r--r-- 4,053 bytes parent folder | download
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
The member function adaptors introduced in this section allow the use of
generic algorithms when the function to call is a member function of a
class. They are, however, deprecated in the upcoming i(C++17) standard, as
their use can easily be replaced by tt(bind) (cf. section(BIND)). The member
function adaptors are briefly mentioned, followed by an illustration of how
tt(bind) can be used instead.

Consider the following class:
        verb(
    class Data
    {
        public:
            void display();
    };
        )
    Obviously, the tt(display) member is used to display the information
stored in tt(Data) objects.

    When storing tt(Data) objects in a vector the tt(for_each) generic
algorithm cannot easily be used to call the tt(display) member for each of the
objects stored in the vector, as tt(for_each) accepts either a (non-member)
function or a function object as its third argument, but does not accept a
member function.

    The member function adaptor tt(mem_fun_ref) and tt(bind) can be used to
solve this problem. tt(Mem_fun_ref) expects the address of a member function
not defining any parameters, and tt(mem_fun_ref's) function call operator
calls that function for the object that is passed as argument to its function
call operator. The example shows its use, as well as an alternative using
tt(bind) (using namespaces tt(std) and tt(placeholders) is assumed): 
        verb(
    int main()
    {
        vector<Data> data;
                                            // deprecated in C++17
        for_each(data.begin(), data.end(), mem_fun_ref(&Data::display));

                                            // alternative, using bind
        for_each(data.begin(), data.end(), bind(&Data::display, _1));
    }
        )

A second member function adaptor is tt(mem_fun), which is used to call a
member function from a em(pointer) to an object. Here tt(bind) can also be
used, as it detects the pointers (as well as tt(shared_ptr) objects, if used)
in the vector tt(data): 
        verb(
    int main()
    {
        vector<Data *> data { new Data };

                                            // deprecated in C++17
        for_each(data.begin(), data.end(), mem_fun(&Data::display));

                                            // alternative, using bind
        for_each(data.begin(), data.end(), bind(&Data::display, _1));

        delete data[0];
    }
        )

    COMMENT(
An interesting observation is that tlurl(http://www.sgi.com) provides an
example of the use of tt(mem_fun) where polymorphic members are used. If
tt(Data::display) is a virtual member function and tt(Derived1) and
tt(Derived2) (both derived from tt(Data)) provide their own implementations of
tt(display), then pointers to tt(Derived1) and tt(Derived2) objects can be
entered into the tt(data) vector. The tt(for_each) algorithm then calls
the proper (overridden) tt(display) function. E.g.,
        verb(
    int main()
    {
        vector<Data *> data;

        data.push_back(new Derived1);
        data.push_back(new Derived2);

                                        // calls Derived1::display or
                                        // Derived2::display.
        for_each(data.begin(), data.end(), mem_fun(&Data::display));
    }
        )
    This example, however, uses public virtual members, confounding the
virtual and public interfaces of classes (cf. section ref(INHERITWHY)) and is
therefore deprecated. Polymorphism could still be used, though, but the
public interface should be provided by tt(Data) as follows:
        verb(
    class Data
    {
        public:
            void display();             // calls v_display
        private:
            virtual void v_display();   // overriden by derived
    };                                  // classes
        )
    In the above example tt(mem_fun) would simply receive tt(&Data::display)'s
address. No need to modify the above tt(main) function, but now tt(Data)'s
polymorphic features are completely separated from its public interface.
    END)