Newer
Older
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// $Id$
#ifndef DUNE_TUPLES_HH
#define DUNE_TUPLES_HH
#include <ostream>
namespace Dune
{
/** @addtogroup Common
*
* @{
*/
/**
* @file
* @brief Contains classes that implement tuples.
*
* This a refined implementation of the approach defined in
* in the article "Tuples and multiple return values
* in C++" of Jaakko Järvi (Turku Centre of Computer
* Science, TUCS Technical Report No 249, March 1999,
* ISBN 952-12-0401-X, ISSN 1239-1891) available from the
* <a href="http://www.tucs.fi/publications/">TUCS publications archive</a>
* @author Markus Blatt
*/
/**
* @brief An empty class.
*/
struct Nil
{};
namespace
{
inline const Nil nullType()
{
return Nil();
}
}
template<class T>
struct TupleAccessTraits
{
typedef const T& ConstType;
typedef T& NonConstType;
typedef const typename ConstantVolatileTraits<T>::UnqualifiedType& ParameterType;
};
template<class T>
struct TupleAccessTraits<T&>
{
typedef T& ConstType;
typedef T& NonConstType;
typedef T& ParameterType;
};
/**
* @brief A tuple consisting of two objects.
*
* This is similar to std::pair
*/
template<typename T1, typename TT>
{
/**
* @brief The type of the first field.
*/
typedef T1 Type1;
/**
* @brief The type of the first field.
*/
typedef TT Type2;
// enum{
// /**
// * @brief The number of values we hold.
// */
// values = 2;
// };
/**
* @brief Constructor
*
* @param t1 The value of the first field.
* @param t2 The value of the second field.
*/
template<typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
Pair(typename TupleAccessTraits<T1>::ParameterType t1, T2& t2, T3& t3, T4& t4, T5& t5,
T6& t6, T7& t7, T8& t8, T9& t9);
Adrian Burri
committed
/**
* @brief Constructor
*
* @param t1 The value of the first field.
* @param t2 The value of the second field.
*/
Pair(typename TupleAccessTraits<Type1>::ParameterType t1, TT& t2);
Pair();
Adrian Burri
committed
/**
* @brief Copy Constructor for implicit type conversion
* @param other The tuple to copy.
*/
template<typename U1, typename U2>
Pair(const Pair<U1,U2>& other);
/**
* @brief Assignment operator for implicit type conversion
* @param other The tuple to assign.
*/
template<typename U1, typename U2>
Pair& operator=(const Pair<U1,U2>& other);
Pair& operator=(const Pair& other);
/**
* @brief Get the first value
* @return The first value
*/
typename TupleAccessTraits<Type1>::NonConstType first();
/**
* @brief Get the first value
* @return The first value
*/
typename TupleAccessTraits<Type1>::ConstType
first() const;
/**
* @brief Get the second value
* @return The first value
*/
typename TupleAccessTraits<Type2>::NonConstType
second();
/**
* @brief Get the first value
* @return The second value
*/
typename TupleAccessTraits<Type2>::ConstType
second() const;
/** @brief The value of the first field. */
Type1 first_;
/** @brief The value of the second field. */
Type2 second_;
};
/**
* @brief A tuple consisting of one object.
* Specialization of Pair that really is a single value.
*/
template<typename T1>
{
/**
* @brief The type of the first field.
*/
typedef T1 Type1;
/**
* @brief The type of the (non-existent) second field is Nil.
* This typedef is useful in template metaprogramming, since it allows
* you to specialise for Nil instead of Pair<T, Nil>
*/
typedef Nil Type2;
/**
* @brief Constructor.
* @param t1 The values for the first field.
* @param t2 The value for the second field.
*/
Pair(typename TupleAccessTraits<T1>::ParameterType first, const Nil&, const Nil&, const Nil&, const Nil&,
const Nil&, const Nil&, const Nil&, const Nil&);
Adrian Burri
committed
/**
* @brief Constructor.
* @param t1 The values for the first field.
* @param t2 The value for the second field.
*/
Pair(typename TupleAccessTraits<T1>::ParameterType first,
const Nil&);
Pair();
Adrian Burri
committed
/**
* @brief Copy constructor for type conversion.
*/
template<typename T2>
Pair(const Pair<T2,Nil>& other);
/**
* @brief Assignment operator for type conversion.
*/
template<typename T2>
Pair& operator=(const Pair<T2,Nil>& other);
/**
* @brief Assignment operator.
*/
Pair& operator=(const Pair& other);
/**
* @brief Get the first value
* @return The first value
*/
typename TupleAccessTraits<Type1>::NonConstType
first();
/**
* @brief Get the first value
* @return The first value
*/
typename TupleAccessTraits<Type1>::ConstType
first() const;
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
/** @brief The value of the first field.*/
Type1 first_;
};
/**
* @brief Converts the Tuple to a list of pairs.
*/
template<typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
struct TupleToPairs
{
typedef Pair<T1, typename TupleToPairs<T2,T3,T4,T5,T6,T7,T8,T9,Nil>::Type > Type;
};
/**
* @brief Specialization for a tuple consisting only of one type.
*/
template<typename T1>
struct TupleToPairs<T1,Nil,Nil,Nil,Nil,Nil,Nil,Nil,Nil>
{
typedef Pair<T1,Nil> Type;
};
/**
* @brief A Tuple of objects.
*
* A maximum of 9 objects is supported.
*
* Use the following construction to access the individual elements.
\code
Tuple<std::string, float*, int> my_tuple;
std:string& s = Element<0>::get(my_tuple);
float* p = Element<1>::get(my_tuple);
// Access the third element in a generic way
typedef ElementType<2, Tuple<std::string, float*, int> >::Type Type;
Type& i = Element<2>::get(my_tuple);
\endcode
*/
template<typename T1, typename T2 = Nil, typename T3 = Nil,
typename T4 = Nil, typename T5 = Nil,typename T6 = Nil,
typename T7 = Nil, typename T8 = Nil, typename T9 = Nil>
class Tuple : public TupleToPairs<T1,T2,T3,T4,T5,T6,T7,T8,T9>::Type
{
public:
Adrian Burri
committed
//! Type of the first Pair defining the Tuple
typedef typename TupleToPairs<T1,T2,T3,T4,T5,T6,T7,T8,T9>::Type FirstPair;
Tuple()
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1)
: FirstPair(t1, nullType(), nullType(), nullType(),
nullType(), nullType(), nullType(), nullType(),
nullType())
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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2)
: FirstPair(t1, t2, nullType(), nullType(),
nullType(), nullType(), nullType(), nullType(),
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3)
: FirstPair(t1, t2, t3, nullType(),
nullType(), nullType(), nullType(), nullType(),
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3,
typename TupleAccessTraits<T4>::ParameterType t4)
: FirstPair(t1, t2, t3, t4,
nullType(), nullType(), nullType(), nullType(),
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3,
typename TupleAccessTraits<T4>::ParameterType t4,
typename TupleAccessTraits<T5>::ParameterType t5)
: FirstPair(t1, t2, t3, t4,
t5, nullType(), nullType(), nullType(),
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3,
typename TupleAccessTraits<T4>::ParameterType t4,
typename TupleAccessTraits<T5>::ParameterType t5,
typename TupleAccessTraits<T6>::ParameterType t6)
: FirstPair(t1, t2, t3, t4,
t5, t6, nullType(), nullType(),
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3,
typename TupleAccessTraits<T4>::ParameterType t4,
typename TupleAccessTraits<T5>::ParameterType t5,
typename TupleAccessTraits<T6>::ParameterType t6,
typename TupleAccessTraits<T7>::ParameterType t7)
: FirstPair(t1, t2, t3, t4,
t5, t6, t7, nullType(),
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3,
typename TupleAccessTraits<T4>::ParameterType t4,
typename TupleAccessTraits<T5>::ParameterType t5,
typename TupleAccessTraits<T6>::ParameterType t6,
typename TupleAccessTraits<T7>::ParameterType t7,
typename TupleAccessTraits<T8>::ParameterType t8)
: FirstPair(t1, t2, t3, t4,
t5, t6, t7, t8,
nullType())
{}
Tuple(typename TupleAccessTraits<T1>::ParameterType t1,
typename TupleAccessTraits<T2>::ParameterType t2,
typename TupleAccessTraits<T3>::ParameterType t3,
typename TupleAccessTraits<T4>::ParameterType t4,
typename TupleAccessTraits<T5>::ParameterType t5,
typename TupleAccessTraits<T6>::ParameterType t6,
typename TupleAccessTraits<T7>::ParameterType t7,
typename TupleAccessTraits<T8>::ParameterType t8,
typename TupleAccessTraits<T9>::ParameterType t9)
: FirstPair(t1, t2, t3, t4, t5, t6, t7, t8, t9)
{}
template<class U1, class U2>
Tuple& operator=(const Pair<U1,U2>& other)
{
FirstPair::operator=(other);
return *this;
}
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
};
/**
* @brief Get the type of the N-th element of the tuple.
*/
template<int N, class Tuple>
struct ElementType;
template<int N, typename T1, typename T2>
struct ElementType<N,Pair<T1,T2> >
{
/**
* @brief The type of the N-th element of the tuple.
*/
typedef typename ElementType<N-1,T2>::Type Type;
};
/**
* @brief Get the type of the first element of the tuple.
*/
template<typename T1, typename T2>
struct ElementType<0, Pair<T1,T2> >
{
/**
* @brief The type of the first element of the tuple.
*/
typedef T1 Type;
};
/**
* @brief Get the N-th element of a tuple.
*/
template<int N>
struct Element
{
/**
* @brief Get the N-th element of the tuple.
* @param tuple The tuple whose N-th element we want.
* @return The N-th element of the tuple.
*/
template<typename T1, typename T2>
static typename ElementType<N,Pair<T1,T2> >::Type& get(Pair<T1,T2>& tuple)
{
return Element<N-1>::get(tuple.second());
}
/**
* @brief Get the N-th element of the tuple.
* @param tuple The tuple whose N-th element we want.
* @return The N-th element of the tuple.
*/
template<typename T1, typename T2>
static const typename ElementType<N,Pair<T1,T2> >::Type& get(const Pair<T1,T2>& tuple)
{
return Element<N-1>::get(tuple.second());
}
};
/**
* @brief Get the first element of a tuple.
*/
template<>
struct Element<0>
{
/**
* @brief Get the first element of the tuple.
* @param tuple The tuple whose first element we want.
* @return The first element of the tuple.
*/
template<typename T1, typename T2>
static T1& get(Pair<T1,T2>& tuple)
{
return tuple.first();
}
/**
* @brief Get the first element of the tuple.
* @param tuple The tuple whose first element we want.
* @return The first element of the tuple.
*/
template<typename T1, typename T2>
static const T1& get(const Pair<T1,T2>& tuple)
{
return tuple.first();
}
};
/**
* @brief Equality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple,
*/
template<typename T1, typename T2, typename U1, typename U2>
inline bool operator==(const Pair<T1,T2>& tuple1, const Pair<U1,U2>& tuple2)
{
return (tuple1.first()==tuple2.first() && tuple1.second()==tuple2.second());
}
/**
* @brief Inequality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple,
*/
template<typename T1, typename T2, typename U1, typename U2>
inline bool operator!=(const Pair<T1,T2>& tuple1, const Pair<U1,U2>& tuple2)
{
return (tuple1.first()!=tuple2.first() || tuple1.second()!=tuple2.second());
}
/**
* @brief Equality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple,
*/
template<typename T1,typename U1>
inline bool operator==(const Pair<T1,Nil>& tuple1, const Pair<U1,Nil>& tuple2)
{
return (tuple1.first()==tuple2.first());
}
/**
* @brief Inequality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple,
*/
template<typename T1, typename U1>
inline bool operator!=(const Pair<T1,Nil>& tuple1, const Pair<U1,Nil>& tuple2)
{
return (tuple1.first()!=tuple2.first());
}
/**
* @brief Equality comparison operator for tuples.
*
* @param tuple1 The first tuple.
* @param tuple2 The second tuple.
* @return False as the type of the compared objects are different.
*/
template<typename T1,typename U1, typename U2>
inline bool operator==(const Pair<T1,Nil>& tuple1, const Pair<U1,U2>& tuple2)
{
return false;
}
/**
* @brief Inequality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple.
* @return True as the type of the compared objects are different.
*/
template<typename T1, typename U1, typename U2>
inline bool operator!=(const Pair<T1,Nil>& tuple1, const Pair<U1,U2>& tuple2)
{
return true;
}
/**
* @brief Equality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple.
* @return False as the type of the compared objects are different.
*/
template<typename T1, typename T2, typename U1>
inline bool operator==(const Pair<T1,T2>& tuple1, const Pair<U1,Nil>& tuple2)
{
return false;
}
/**
* @brief Inequality comparison operator for tuples.
* @param tuple1 The first tuple.
* @param tuple2 The second tuple.
* @return True as the type of the compared objects are different.
*/
template<typename T1, typename T2, typename U1>
inline bool operator!=(const Pair<T1,T2>& tuple1, const Pair<U1,Nil>& tuple2)
{
return true;
}
/**
* @brief Create a tuple and initialize it.
* @param first The value of the first field.
* @param second The value of the second field.
*/
template<typename T1, typename T2>
inline Pair<T1,T2> makePair(const T1& first, const T2& second)
{
return Pair<T1,T2>(first, second);
}
/**
* @brief Print a pair or tuple.
*/
template<typename T1, typename T2>
inline std::ostream& operator<<(std::ostream& os, const Pair<T1,T2>& pair)
{
os<<pair.first()<<" "<<pair.second();
return os;
}
template<typename T1>
inline std::ostream& operator<<(std::ostream& os, const Pair<T1,Nil>& pair)
{
os<<pair.first();
return os;
}
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
template<class T1>
inline Tuple<T1&> tie(T1& t1) {
return Tuple<T1&> (t1);
}
template<class T1, class T2>
inline Tuple<T1&, T2&> tie(T1& t1, T2& t2) {
return Tuple<T1&, T2&> (t1, t2);
}
template<class T1, class T2, class T3>
inline Tuple<T1&, T2&, T3&> tie(T1& t1, T2& t2, T3& t3) {
return Tuple<T1&, T2&, T3&> (t1, t2, t3);
}
template<class T1, class T2, class T3, class T4>
inline Tuple<T1&, T2&, T3&, T4&> tie(T1& t1, T2& t2, T3& t3, T4& t4) {
return Tuple<T1&, T2&, T3&, T4&> (t1, t2, t3, t4);
}
template<class T1, class T2, class T3, class T4, class T5>
inline Tuple<T1&, T2&, T3&, T4&, T5&>
tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) {
return Tuple<T1&, T2&, T3&, T4&, T5&> (t1, t2, t3, t4, t5);
}
template<class T1, class T2, class T3, class T4, class T5, class T6>
inline Tuple<T1&, T2&, T3&, T4&, T5&, T6&>
tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6) {
return Tuple<T1&, T2&, T3&, T4&, T5&, T6&> (t1, t2, t3, t4, t5, t6);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
inline Tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&>
tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7) {
return Tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&> (t1, t2, t3, t4, t5, t6, t7);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
class T8>
inline Tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>
tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8) {
return Tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>
(t1, t2, t3, t4, t5, t6, t7, t8);
}
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7,
class T8, class T9>
inline Tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>
tie(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9) {
return Tuple<T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>
(t1, t2, t3, t4, t5, t6, t7, t8, t9);
}
template<typename T1, typename TT>
template<typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9>
inline Pair<T1,TT>::Pair(typename TupleAccessTraits<T1>::ParameterType first,
T2& t2, T3& t3, T4& t4, T5& t5,
T6& t6, T7& t7, T8& t8, T9& t9)
: first_(first), second_(t2,t3,t4,t5,t6,t7,t8,t9, nullType())
Adrian Burri
committed
template <typename T1, typename TT>
inline Pair<T1, TT>::Pair(typename TupleAccessTraits<T1>::ParameterType first, TT& second)
Adrian Burri
committed
: first_(first), second_(second)
{}
template<typename T1, typename T2>
inline Pair<T1,T2>::Pair()
: first_(), second_()
{}
template<typename T1, typename T2>
template<typename U1, typename U2>
inline Pair<T1,T2>::Pair(const Pair<U1,U2>& other)
: first_(other.first_), second_(other.second_)
{}
template<typename T1, typename T2>
template<typename U1, typename U2>
inline Pair<T1,T2>& Pair<T1,T2>::operator=(const Pair<U1,U2>& other)
{
first_=other.first_;
second_=other.second_;
return *this;
}
template<typename T1, typename T2>
inline Pair<T1,T2>& Pair<T1,T2>::operator=(const Pair& other)
{
first_=other.first_;
second_=other.second_;
return *this;
}
template<typename T1, typename T2>
inline typename TupleAccessTraits<T1>::NonConstType
Pair<T1,T2>::first()
{
return first_;
}
template<typename T1, typename T2>
inline typename TupleAccessTraits<T1>::ConstType
Pair<T1,T2>::first() const
{
return first_;
}
template<typename T1, typename T2>
inline typename TupleAccessTraits<T2>::NonConstType
Pair<T1,T2>::second()
{
return second_;
}
template<typename T1, typename T2>
inline typename TupleAccessTraits<T2>::ConstType
Pair<T1,T2>::second() const
{
return second_;
}
template<typename T1>
inline Pair<T1,Nil>::Pair(typename TupleAccessTraits<T1>::ParameterType first,
const Nil&, const Nil&, const Nil&, const Nil&,
const Nil&, const Nil&, const Nil&, const Nil&)
: first_(first)
{}
Adrian Burri
committed
template <typename T1>
inline Pair<T1, Nil>::Pair(typename TupleAccessTraits<T1>::ParameterType first,
const Nil&)
Adrian Burri
committed
: first_(first)
{}
template<typename T1>
inline Pair<T1,Nil>::Pair()
: first_()
{}
template<typename T1>
template<typename T2>
inline Pair<T1,Nil>::Pair(const Pair<T2,Nil>& other)
: first_(other.first_)
{}
template<typename T1>
template<typename T2>
Pair<T1,Nil>& Pair<T1,Nil>::operator=(const Pair<T2,Nil>& other)
{
first_ = other.first_;
return *this;
}
template<typename T1>
Pair<T1,Nil>& Pair<T1,Nil>::operator=(const Pair& other)
{
first_ = other.first_;
return *this;
}
inline typename TupleAccessTraits<T1>::NonConstType
Pair<T1,Nil>::first()
{
return first_;
}
template<typename T1>
inline typename TupleAccessTraits<T1>::ConstType
Pair<T1,Nil>::first() const
{
return first_;
}
}
#endif