Newer
Older
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_UTILITY_HH
#define DUNE_UTILITY_HH
#include "tuples.hh"
namespace Dune {
/** @ addtogroup Common
*
* @{
*/
/**
* @file
* @brief Contain utility classes which can be used with tuples.
*/
/**
* @brief A helper template that initializes a tuple consisting of pointers
* to NULL.
*
* A tuple of NULL pointers may be useful when you use a tuple of pointers
* in a class which you can only initialise in a later stage.
*/
template <class PairT>
class NullPointerInitialiser {};
/**
* @brief Specialisation for standard tuple element.
*/
template <class Head, class Tail>
class NullPointerInitialiser<Pair<Head*, Tail> > {
public:
//! The subpart of the tuple which is handed back to the next instance
//! of the NullPointerInitialiser.
typedef Pair<Head*, Tail> ResultType;
public:
//! Static method to build up tuple.
static inline ResultType apply() {
return ResultType(0, NullPointerInitialiser<Tail>::apply());
}
};
/**
* @brief Specialisation for last (Nil) element.
*/
template <>
class NullPointerInitialiser<Nil> {
public:
//! The return type of the close is Nil.
typedef Nil ResultType;
public:
//! Provide closure of tuple
static inline ResultType apply() {
return Nil();
}
};
/**
* @brief Deletes all objects pointed to in a tuple of pointers.
*
* \warning Pointers cannot be set to NULL, so calling the Deletor twice
* or accessing elements of a deleted tuple leads to unforeseeable results!
*/
template <class PairT>
struct PointerPairDeletor {};
/**
* @brief Specialisation for a standard tuple element.
*/
template <class Head, class Tail>
struct PointerPairDeletor<Pair<Head*, Tail> > {
//! Deletes object pointed to by first element and triggers deletion on
//! subsequent pairs.
static void apply(Pair<Head*, Tail>& p) {
delete p.first();
PointerPairDeletor<Tail>::apply(p.second());
}
};
/**
* @brief Specialisation for last (non-Nil) tuple element.
*/
template <class Head>
struct PointerPairDeletor<Pair<Head*, Nil> > {
//! Deletes object pointed to by first element.
static void apply(Pair<Head*, Nil>& p) {
delete p.first();
}
};
/**
* @brief Helper template to calculate length of a tuple.
*/
template <class PairT>
struct Length {};
/**
* @brief Specialisation for a standard tuple element.
*
* The length of the tuple is stored by the enumeration value.
*/
template <class Head, class Tail>
struct Length<Pair<Head, Tail> > {
//! The length of the (sub)tuple.
enum { value = 1 + Length<Tail>::value };
};
/**
* @brief Specialisation for the closure.
*/
template <>
struct Length<Nil> {
//! The length of an empty tuple is zero by definition.
enum { value = 0 };
};
/**
* @brief Helper template to clone the type definition of a tuple with the
* storage types replaced by a user-defined rule.
*
* Suppose all storage types A_i in a tuple define a type A_i::B. You can
* build up a pair consisting of the types defined by A_i::B in the following
* way:
\code
template <class A>
struct MyEvaluator {
typedef typename A::B Type;
};
typedef ForEachType<MyEvaluator, ATuple>::Type BTuple;
\endcode
* Here, MyEvaluator is a helper struct that extracts the correct type from
* the storage types of the tuple defined by the tuple ATuple.
*/
template <template <class> class TypeEvaluator, class TupleType>
struct ForEachType {};
/**
* @brief Specialisation for standard tuple element
*/
template <template <class> class TypeEvaluator, class Head, class Tail>
struct ForEachType<TypeEvaluator, Pair<Head, Tail> > {
//! Defines type corresponding to the subtuple defined by Pair<Head, Tail>
typedef Pair<typename TypeEvaluator<Head>::Type,
typename ForEachType<TypeEvaluator, Tail>::Type> Type;
};
/**
* @brief Specialisation for last element
*/
template <template <class> class TypeEvaluator>
struct ForEachType<TypeEvaluator, Nil> {
typedef Nil Type;
};
// template <template <class> class TypeEvaluator, class Head>
// struct ForEachType<TypeEvaluator, Pair<Head, Nil> > {
// //! For the storage element, Head is replaced by the expression provided
// //! by the TypeEvaluator helper template.
// typedef Pair<typename TypeEvaluator<Head>::Type, Nil> Type;
// };
/**
* @brief Helper template which implements iteration over all storage
* elements in a tuple.
*
* Compile-time constructs that allows to process all elements in a tuple.
* The exact operation performed on an element is defined by a function
* object, which needs to implement a visit method which is applicable to
* all storage elements of a tuple.
*
* The following example implements a function object which counts the
* elements in a tuple
\code
template <class T>
struct Counter {
Counter() : result_(0) {}
template <class T>
void visit(T& elem) { ++result_; }
int result_;
};
\endcode
* The number of elements in the tuple are stored in the member variable
* result_. The Counter can be used as follows, assuming a tuple t of type
* MyTuple is given:
\code
Counter c;
ForEachValue<MyTuple> forEach(t);
forEach.apply(c);
std::cout << "Number of elements is: " << c.result_ << std::endl;
\endcode
*/
template <class TupleType>
class ForEachValue {
public:
//! \brief Constructor
//! \param tuple The tuple which we want to process.
ForEachValue(TupleType& tuple) : tuple_(tuple) {}
//! \brief Applies a function object to each storage element of the tuple.
//! \param f Function object.
template <class Functor>
void apply(Functor& f) {
apply(f, tuple_);
}
private:
//! Specialisation for the last element
template <class Functor, class Head>
void apply(Functor& f, Pair<Head, Nil>& last) {
f.visit(last.first());
}
//! Specialisation for a standard tuple element
template <class Functor, class Head, class Tail>
void apply(Functor& f, Pair<Head, Tail>& pair) {
f.visit(pair.first());
apply(f, pair.second());
}
private:
TupleType& tuple_;
};
//- Definition ForEachValuePair class
// Assertion: both tuples have the same length and the contained types are
// compatible in the sense of the applied function object
/**
* @brief Extension of ForEachValue to two tuples...
*
* This class provides the framework to process two tuples at once. It works
* the same as ForEachValue, just that the corresponding function object
* takes one argument from the first tuple and one argument from the second.
*
* \note You have to ensure that the two tuples you provide are compatible
* in the sense that they have the same length and that the objects passed
* to the function objects are related in meaningful way. The best way to
* enforce it is to build the second tuple from the existing first tuple
* using ForEachType.
*/
template <class TupleType1, class TupleType2>
class ForEachValuePair {
public:
//! Constructor
//! \param t1 First tuple.
//! \param t2 Second tuple.
ForEachValuePair(TupleType1& t1, TupleType2& t2) :
tuple1_(t1),
tuple2_(t2)
{}
//! Applies the function object f to the pair of tuples.
//! \param f The function object to apply on the pair of tuples.
template <class Functor>
void apply(Functor& f) {
apply(f, tuple1_, tuple2_);
}
private:
//! Specialisation for the last element.
template <class Functor, class Head1, class Head2>
void apply(Functor& f, Pair<Head1, Nil>& last1, Pair<Head2, Nil>& last2) {
f.visit(last1.first(), last2.first());
}
//! Specialisation for a standard element.
template <class Functor, class Head1, class Tail1, class Head2,class Tail2>
void apply(Functor& f, Pair<Head1, Tail1>& p1, Pair<Head2, Tail2>& p2) {
f.visit(p1.first(), p2.first());
apply(f, p1.second(), p2.second());
}
private:
TupleType1& tuple1_;
TupleType2& tuple2_;
};
//- Reverse element access
/**
* @brief Type for reverse element access.
*
* Counterpart to ElementType for reverse element access.
*/
template <int N, class Tuple>
struct AtType {
typename ElementType<Length<Tuple>::value - N - 1,
Tuple>::Type Type;
};
/**
* @brief Reverse element access.
*
* While Element<...> gives you the arguments beginning at the front of a
* tuple, At<...> starts at the end, which may be more convenient, depending
* on how you built your tuple.
*/
template <int N>
struct At
{
template <class T1, class T2>
static typename ElementType<Length<Pair<T1, T2> >::value - N - 1,
Pair<T1, T2> >::Type&
get(Pair<T1, T2>& tuple) {
return Element<Length<Pair<T1, T2> >::value - N - 1>::get(tuple);
}
template <class T1, class T2>
static const typename ElementType<Length<Pair<T1, T2> >::value - N - 1,
Pair<T1, T2> >::Type&
get(const Pair<T1, T2>& tuple) {
return Element<Length<Pair<T1, T2> >::value - N - 1>::get(tuple);
}
};
}
#endif