File: binopclasses.cc

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (130 lines) | stat: -rw-r--r-- 3,158 bytes parent folder | download | duplicates (5)
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
#include <istream>
#include <ostream>
#include <utility>

    // The complete interface of the class template Binops: if additional
    // operators are overloaded Binops requires no modifications.
    //
template <typename Derived>
class Binops
{
    template <typename Der>
    friend std::ostream &operator<<(
                            std::ostream &out, Binops<Der> const &rhs);

    template <typename Der>
    friend std::istream &operator>>(std::istream &in, Binops<Der> &rhs);

    void eWrap(std::istream &in);
    void iWrap(std::ostream &out) const;
};

    // Completing the overloads for operator+: all function templates, that
    // depend on operator+=(...) defined in Derived
    //
template <class Derived, typename Rhs>
Derived &operator+=(Binops<Derived> &lhs, Rhs const &rhs)
{
    Derived tmp{ Derived{static_cast<Derived &>(lhs)} += rhs };
    tmp.swap(static_cast<Derived &>(lhs));
    return static_cast<Derived &>(lhs);
}

template <class Derived, typename Rhs>
Derived operator+(Binops<Derived> &&lhs, Rhs const &rhs)
{
    return static_cast<Derived &&>(std::move(lhs)) += rhs;
}

template <class Derived, typename Rhs>
Derived operator+(Binops<Derived> const &lhs, Rhs const &rhs)
{
    return Derived{static_cast<Derived const &>(lhs)} += rhs;
}

    // Other operators may be added here, and are implemented analogously, see
    // the Annotations.

    // Implementing the insertion operator. The extraction operator is
    // implemented analogously, see the Annotations:
    //
template <typename Derived>
inline void Binops<Derived>::iWrap(std::ostream &out) const
{
    static_cast<Derived const &>(*this).insert(out);
}

template <typename Derived>
inline std::ostream &operator<<(std::ostream &out, Binops<Derived> const &rhs)
{
    rhs.iWrap(out);
    return out;
}






////////////////////////////////////////////////////////////////////////

    // User area: the user defines a class Derived, and wants to provide
    // addition and insertion: the operator+=() && and insert() functions have
    // to be implemented and Derived derives from Binops<Derived>. For insert
    // a friend declaration is also required.

#include <iostream>

using namespace std;

class Derived: public Binops<Derived>
{
    friend Binops<Derived>; // only required for stream insertion/extraction

    int d_value = 0;

    public:
        Derived() = default;

        Derived(int value)
        :
            d_value(value)
        {}

        void swap(Derived &other);

        Derived &&operator+=(Derived const &rhs) &&;

    private:
        void insert(std::ostream &out) const;
};

inline void Derived::insert(std::ostream &out) const
{
    out << "Inserting a Derived object";
}

Derived &&Derived::operator+=(Derived const &rhs) &&
{
    d_value += rhs.d_value;
    return std::move(*this);
}

inline void Derived::swap(Derived &rhs)
{
    std::swap(d_value, rhs.d_value);
}

int main()
{
    Derived o1{ 1 },
    Derived o2{ 2 };
    o1 += o2;
    // o1 *= o2;            // adding this statement results in
                            // a compilation error

    o1 = o1 + o2;
    o1 += o1;

    cout << o1 << '\n';
}