File: increment.yo

package info (click to toggle)
c%2B%2B-annotations 8.2.0-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 11,804 kB
  • ctags: 2,845
  • sloc: cpp: 15,418; makefile: 2,473; ansic: 165; perl: 90; sh: 29
file content (108 lines) | stat: -rw-r--r-- 4,299 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
Overloading the i(increment operator) hi(operator++)(tt(operator++)) and
    i(decrement operator) hi(operator--)(opdecrement()) introduces a small
problem: there are two versions of each operator, as they may be used as
em(postfix operator) (e.g., tt(x++)) or as em(prefix operator) (e.g.,
tt(++x)).

    Used as em(postfix) operator, the value's object is returned as an
emi(rvalue), temporary const object and the post-incremented variable itself
disappears from view. Used as em(prefix) operator, the variable is
incremented, and its value is returned as emi(lvalue) and it may be altered
again by modifying the prefix operator's return value. Whereas these
characteristics are not em(required) when the operator is overloaded, it is
strongly advised to implement these characteristics in any overloaded
increment or decrement operator.

    Suppose we define a emi(wrapper class) around the tt(size_t) value
type. Such a class could offer the following (partially shown) interface:
        verb(
    class Unsigned
    {
        size_t d_value;

        public:
            Unsigned();
            explicit Unsigned(size_t init);

            Unsigned &operator++();
    }
        )
    The class's last member declares the em(prefix) overloaded increment
operator. The returned  em(lvalue) is tt(Unsigned &). The member is easily implemented:
        verb(
    Unsigned &Unsigned::operator++()
    {
        ++d_value;
        return *this;
    }
        )

    To define the em(postfix) operator, an overloaded version of the operator
is defined, expecting a (dummy) tt(int) argument. This might be considered a
emi(kludge), or an acceptable application of function overloading. Whatever
your opinion in this matter, the following can be concluded:
    itemization(
    it() Overloaded increment and decrement operators em(without parameters)
are em(prefix) operators, and should return em(references) to the current
object.
    it() Overloaded increment and decrement operators em(having an int
parameter) are em(postfix) operators, and should return a constant value which
is a copy of the object at the point where its postfix operator is used.
    )
    The postfix increment operator is declared as follows in the class
tt(Unsigned)'s interface:
        verb(
    Unsigned const operator++(int);
        )
    It may be implemented as follows:
        verb(
    Unsigned const Unsigned::operator++(int)
    {
        Unsigned tmp(*this);
        ++d_value;
        return tmp;
    }
        )
    Note that the operator's parameter is not used. It is only part of the
implementation to em(disambiguate) the prefix- and postfix operators in
implementations and declarations.

    In the above example the statement incrementing the current object offers
the em(nothrow) guarantee as it only involves an operation on a
primitive type. If the initial copy construction throws then the original
object is not modified, if the return statement throws the object has safely
been modified. But incrementing an object could itself throw exceptions. How
to implement the increment operators in that case? Once again, tt(swap) is our
friend. Here are the pre- and postfix operators offering the strong guarantee
when the member tt(increment) performing the increment operation may throw:
        verb(
    Unsigned &Unsigned::operator++()
    {
        Unsigned tmp(*this);
        tmp.increment();
        swap(tmp);
        return *this;
    }
    Unsigned const Unsigned::operator++(int)
    {
        Unsigned tmp(*this);
        tmp.increment();
        swap(tmp);
        return tmp;
    }
        )
    The postfix increment operator first creates a copy of the current
object. That copy is incremented and then swapped with the current object. If
tt(increment) throws the current object remains unaltered; the swap operation
ensures that the original object is returned and the current object becomes
the incremented object.

    When calling  the postfix increment or decrement operator
using  its full member function name then any tt(int) argument passed to the
member function will result in calling the postfix operator. Example:
        verb(
    Unsigned uns(13);

    uns.operator++();     // prefix-incrementing uns
    uns.operator++(0);    // postfix-incrementing uns
        )