File: intro.txt

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 (188 lines) | stat: -rw-r--r-- 6,421 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

Alternatively the following syntax can be used:
        verb(
    template< typename Type> requires ComparableBySmaller<Type>
    Type const &min(Type const &x, Type const &y)
    {
        return y < x ? y : x;
    }
        )
    The advantage of the former syntax is that it allows a list of
requirements, e.g., linebreak() tt(ComparableBySmaller<Type>,
Ordered<Type>). Moreover, these requirements may be combined using the
logical negation (! (tt(not))) and conjunction (&& (tt(and))) operators.

To define a concept hi(concept: definition) the following syntax will be
provided:
        verb(
    auto concept ComparableBySmaller <typename Type>
    {
        bool operator<(Type, Type);
    }
        )
    This concept specifies that a type supporting an tt(operator<) accepting
two tt(Type) objects and returning a tt(bool) is a tt(ComparableBySmaller)
type. Note that this therefore becomes an implied characteristic of an actual
type. Any type defining this operator by implication also becomes a
tt(ComparableBySmaller) type. Any such type may therefore be used to
instantiate a template with that requires the tt(ComparableBySmaller) concept.

The C++ standard introduces emi(axiom)em(s) as a feature of concepts.  Axioms
can be used to define properties of concepts, such as their
associativity. Here is a preliminary example of how an axiom could be used in
the definition of a concept:
        verb(
    concept Semigroup< typename Op, typename Type> : CopyConstructible<Type>
    {
        Type operator()(Op, Type, Type);

        axiom Associativity(Op op, Type x, Type y, Type z)
        {
            op(x, op(y, z)) == op(op(x, y), z);
        }
    };
        )

As remarked, concepts and axioms are currently still unavailable in the
tt(g++) compiler. It is likely that this section will be vastly expanded by
the time the compiler has fully implemented the C2a standard. Concepts, axioms
and related constructs may eventually even be covered in a separate chapter.




COMMENT(
    =================================================================
The
operator need not be a free-function; it could be a member function of the
type T.

Concepts can involve multiple objects as well. For example, concepts can
express that a type is convertible from one type to another:

auto concept Convertible< typename T, typename U>
{
  operator U(const T&);
}

In order to use this in a template, it must use a generalized form of concept
usage:

template< typename U, typename T> requires Convertible<T, U>
  U convert(const T& t)
  {
    return t;
  }


Concepts may be composed. For example, given a concept named Regular:

concept InputIterator< typename Iter, typename Value>
{
  requires Regular<Iter>;
  Value operator*(const Iter&);
  Iter& operator++(Iter&);
  Iter operator++(Iter&, int);
}

The first template parameter to the InputIterator concept must conform to the
Regular concept.

Concepts can also be derived from one another, like inheritance. Like in class
inheritance, types that meet the requirements of the derived concept also meet
the requirements of the base concept. It is defined as per class derivation:

concept ForwardIterator< typename Iter, typename Value> : InputIterator<Iter,
Value> {
  //Add other requirements here.
}

Typenames can also be associated with a concept. These impose the requirement
that, in templates that use those concepts, these typenames are available:

concept InputIterator< typename Iter>
{
  typename value_type;
  typename reference;
  typename pointer;
  typename difference_type;
  requires Regular<Iter>;
  requires Convertible<reference, value_type>;
  reference operator*(const Iter&); // dereference
  Iter& operator++(Iter&); // pre-increment
  Iter operator++(Iter&, int); // post-increment
  //...
}

Concept maps allow types to be explicitly bound to a concept. They also allow
types to, where possible, adopt the syntax of a concept without changing the
definition of the type. As an example:

concept_map InputIterator<char*>
{
  using value_type = char;
  using reference = char &;
  using pointer = char *;
  using difference_type = std::ptrdiff_t;
};

This map fills in the required typenames for the InputIterator concept when
applied to char* types.

As an added degree of flexibility, concept maps themselves can be
templated. The above example can be extended to all pointer types:

template< typename T> concept_map InputIterator<T*>
{
  using value_type = T;
  using reference = T &;
  using pointer = T *;
  using difference_type = std::ptrdiff_t;
};

Further, concept maps can act as mini-types, with function definitions and
other constructs commonly associated with classes:

concept Stack< typename X>
{
  typename value_type;
  void push(X&, const value_type&);
  void pop(X&);
  value_type top(const X&);
  bool empty(const X&);
};

template< typename T> concept_map Stack<std::vector<T> >
{
  using value_type = T;
  void push(std::vector<T>& v, const T& x) { v.push_back(x); }
  void pop(std::vector<T>& v) { v.pop_back(); }
  T top(const std::vector<T>& v) { return v.back(); }
  bool empty(const std::vector<T>& v) { return v.empty(); }
};

This concept map allows templates that take types that implement the concept
Stack to take a std::vector, remapping the function calls directly to the
std::vector calls. Ultimately, this allows a pre-existing object to be
converted, without touching the definition of the object, into an interface
that a template function can utilize.

Finally, it should be noted that some requirements can be checked using static
assertions. These can verify some requirements that templates need, but are
really aimed at a different problem.

    ================================================================

Compilers are allowed, but not required, to take advantage of the semantics
specified by axioms to perform optimizations that possibly have side-effects
on the observable behavior of the program, which are typically prohibited
(with few exceptions such as copy constructor elision). In the above example,
compilers may reassociate nested calls to operator() of type Op on several
values of type Type provided that there is a concept map for types Op and Type
to the concept Semigroup.

Axioms can also assist in software verification, software testing, and other
program analyses and transformations.
    ===========================================================
END)