00001
00002
00003
00004 #ifndef DUNE_TUPLE_UTILITY_HH
00005 #define DUNE_TUPLE_UTILITY_HH
00006
00007 #include <cstddef>
00008 #include <tuple>
00009 #include <type_traits>
00010
00011 #include <dune/common/hybridutilities.hh>
00012 #include <dune/common/std/type_traits.hh>
00013 #include <dune/common/std/utility.hh>
00014
00015 namespace Dune {
00016
00027 template<class T>
00028 struct TupleAccessTraits
00029 {
00030 typedef typename std::add_const<T>::type& ConstType;
00031 typedef T& NonConstType;
00032 typedef const typename std::remove_const<T>::type& ParameterType;
00033 };
00034
00035 template<class T>
00036 struct TupleAccessTraits<T*>
00037 {
00038 typedef typename std::add_const<T>::type* ConstType;
00039 typedef T* NonConstType;
00040 typedef T* ParameterType;
00041 };
00042
00043 template<class T>
00044 struct TupleAccessTraits<T&>
00045 {
00046 typedef T& ConstType;
00047 typedef T& NonConstType;
00048 typedef T& ParameterType;
00049 };
00050
00058 template<class T>
00059 struct NullPointerInitialiser;
00060
00061 template<class... Args>
00062 struct NullPointerInitialiser<std::tuple<Args...> >
00063 {
00064 typedef std::tuple<Args...> ResultType;
00065 static ResultType apply()
00066 {
00067 return ResultType(static_cast<Args>(nullptr)...);
00068 }
00069 };
00070
00095 template<template <class> class TE, class T>
00096 struct ForEachType;
00097
00098 template<template <class> class TE, class... Args>
00099 struct ForEachType<TE, std::tuple<Args...> >
00100 {
00101 typedef std::tuple<typename TE<Args>::Type...> Type;
00102 };
00103
00104 #ifndef DOXYGEN
00105 template<class Tuple, class Functor, std::size_t... I>
00106 inline auto genericTransformTupleBackendImpl(Tuple& t, Functor& f, const Std::index_sequence<I...>& )
00107 -> std::tuple<decltype(f(std::get<I>(t)))...>
00108 {
00109 return std::tuple<decltype(f(std::get<I>(t)))...>(f(std::get<I>(t))...);
00110 }
00111
00112 template<class... Args, class Functor>
00113 auto genericTransformTupleBackend(std::tuple<Args...>& t, Functor& f) ->
00114 decltype(genericTransformTupleBackendImpl(t, f,Std::index_sequence_for<Args...>{}))
00115 {
00116 return genericTransformTupleBackendImpl(t, f,Std::index_sequence_for<Args...>{});
00117 }
00118
00119 template<class... Args, class Functor>
00120 auto genericTransformTupleBackend(const std::tuple<Args...>& t, Functor& f) ->
00121 decltype(genericTransformTupleBackendImpl(t, f, Std::index_sequence_for<Args...>{}))
00122 {
00123 return genericTransformTupleBackendImpl(t, f, Std::index_sequence_for<Args...>{});
00124 }
00125 #endif
00126
00165 template<class Tuple, class Functor>
00166 auto genericTransformTuple(Tuple&& t, Functor&& f) ->
00167 decltype(genericTransformTupleBackend(t, f))
00168 {
00169 return genericTransformTupleBackend(t, f);
00170 }
00171
00204 template<template<class> class TE, class... Args>
00205 class TransformTupleFunctor
00206 {
00207 mutable std::tuple<Args&...> tup;
00208
00209 template<class T, std::size_t... I>
00210 inline auto apply(T&& t, const Std::index_sequence<I...>& ) ->
00211 decltype(TE<T>::apply(t,std::get<I>(tup)...)) const
00212 {
00213 return TE<T>::apply(t,std::get<I>(tup)...);
00214 }
00215
00216 public:
00217 template<class T>
00218 struct TypeEvaluator : public TE<T>
00219 {};
00220
00221 TransformTupleFunctor(Args&&... args)
00222 : tup(args...)
00223 { }
00224
00225 template<class T>
00226 inline auto operator()(T&& t) ->
00227 decltype(this->apply(t,Std::index_sequence_for<Args...>{})) const
00228 {
00229 return apply(t,Std::index_sequence_for<Args...>{});
00230 }
00231 };
00232
00233 template<template<class> class TE, class... Args>
00234 TransformTupleFunctor<TE, Args...> makeTransformTupleFunctor(Args&&... args)
00235 {
00236 return TransformTupleFunctor<TE, Args...>(args...);
00237 }
00238
00271 template<template<class> class TypeEvaluator, class Tuple, class... Args>
00272 auto transformTuple(Tuple&& orig, Args&&... args) ->
00273 decltype(genericTransformTuple(orig, makeTransformTupleFunctor<TypeEvaluator>(args...)))
00274 {
00275 return genericTransformTuple(orig, makeTransformTupleFunctor<TypeEvaluator>(args...));
00276 }
00277
00279
00283 template<class T>
00284 struct AddRefTypeEvaluator
00285 {
00286 typedef T& Type;
00287 static Type apply(T& t)
00288 {
00289 return t;
00290 }
00291 };
00292
00294
00298 template<class T>
00299 struct AddPtrTypeEvaluator
00300 {
00301 typedef typename std::remove_reference<T>::type* Type;
00302 static Type apply(T& t)
00303 {
00304 return &t;
00305 }
00306 };
00307
00308
00309 template<class T>
00310 struct AddPtrTypeEvaluator<T&>
00311 {
00312 typedef typename std::remove_reference<T>::type* Type;
00313 static Type apply(T& t)
00314 {
00315 return &t;
00316 }
00317 };
00318
00362 template<class Tuple>
00363 class ForEachValue
00364 {
00365 public:
00368 ForEachValue(Tuple& t) :
00369 t_(t)
00370 {}
00371
00374 template<class Functor>
00375 void apply(Functor& f) const
00376 {
00377 Hybrid::forEach(Std::make_index_sequence<std::tuple_size<Tuple>::value>{},
00378 [&](auto i){f.visit(std::get<i>(t_));});
00379 }
00380 private:
00381 Tuple& t_;
00382 };
00383
00397 template<class Tuple1, class Tuple2>
00398 class ForEachValuePair
00399 {
00400 public:
00404 ForEachValuePair(Tuple1& t1, Tuple2& t2) :
00405 t1_(t1),
00406 t2_(t2)
00407 {}
00408
00411 template<class Functor>
00412 void apply(Functor& f)
00413 {
00414 Hybrid::forEach(Std::make_index_sequence<std::tuple_size<Tuple1>::value>{},
00415 [&](auto i){f.visit(std::get<i>(t1_), std::get<i>(t2_));});
00416 }
00417 private:
00418 Tuple1& t1_;
00419 Tuple2& t2_;
00420 };
00421
00427 template<int N, class Tuple>
00428 struct AtType
00429 {
00430 typedef typename std::tuple_element<std::tuple_size<Tuple>::value - N - 1, Tuple>::type Type;
00431 };
00432
00440 template<int N>
00441 struct At
00442 {
00443 template<typename Tuple>
00444 static typename TupleAccessTraits<typename AtType<N, Tuple>::Type>::NonConstType
00445 get(Tuple& t)
00446 {
00447 return std::get<std::tuple_size<Tuple>::value - N - 1>(t);
00448 }
00449
00450 template<typename Tuple>
00451 static typename TupleAccessTraits<typename AtType<N, Tuple>::Type>::ConstType
00452 get(const Tuple& t)
00453 {
00454 return std::get<std::tuple_size<Tuple>::value - N - 1>(t);
00455 }
00456 };
00457
00461 template<class Tuple>
00462 struct PointerPairDeletor
00463 {
00464 template<typename... Ts>
00465 static void apply(std::tuple<Ts...>& t)
00466 {
00467 Hybrid::forEach(t,[&](auto&& ti){delete ti; ti=nullptr;});
00468 }
00469 };
00470
00494 template<class Tuple, template<class> class Predicate, std::size_t start = 0,
00495 std::size_t size = std::tuple_size<Tuple>::value>
00496 class FirstPredicateIndex :
00497 public std::conditional<Predicate<typename std::tuple_element<start,
00498 Tuple>::type>::value,
00499 std::integral_constant<std::size_t, start>,
00500 FirstPredicateIndex<Tuple, Predicate, start+1> >::type
00501 {
00502 static_assert(std::tuple_size<Tuple>::value == size, "The \"size\" "
00503 "template parameter of FirstPredicateIndex is an "
00504 "implementation detail and should never be set "
00505 "explicitly!");
00506 };
00507
00508 #ifndef DOXYGEN
00509 template<class Tuple, template<class> class Predicate, std::size_t size>
00510 class FirstPredicateIndex<Tuple, Predicate, size, size>
00511 {
00512 static_assert(Std::to_false_type<Tuple>::value, "None of the std::tuple element "
00513 "types matches the predicate!");
00514 };
00515 #endif // !DOXYGEN
00516
00526 template<class T>
00527 struct IsType
00528 {
00530 template<class U>
00531 struct Predicate : public std::is_same<T, U> {};
00532 };
00533
00547 template<class Tuple, class T, std::size_t start = 0>
00548 struct FirstTypeIndex :
00549 public FirstPredicateIndex<Tuple, IsType<T>::template Predicate, start>
00550 { };
00551
00558 template<class Tuple, class T>
00559 struct PushBackTuple;
00560
00561 template<class... Args, class T>
00562 struct PushBackTuple<typename std::tuple<Args...>, T>
00563 {
00564 typedef typename std::tuple<Args..., T> type;
00565 };
00566
00573 template<class Tuple, class T>
00574 struct PushFrontTuple;
00575
00576 template<class... Args, class T>
00577 struct PushFrontTuple<typename std::tuple<Args...>, T>
00578 {
00579 typedef typename std::tuple<T, Args...> type;
00580 };
00581
00594 template<
00595 template <class, class> class F,
00596 class Tuple,
00597 class Seed=std::tuple<>,
00598 int N=std::tuple_size<Tuple>::value>
00599 struct ReduceTuple
00600 {
00601 typedef typename ReduceTuple<F, Tuple, Seed, N-1>::type Accumulated;
00602 typedef typename std::tuple_element<N-1, Tuple>::type Value;
00603
00605 typedef typename F<Accumulated, Value>::type type;
00606 };
00607
00618 template<
00619 template <class, class> class F,
00620 class Tuple,
00621 class Seed>
00622 struct ReduceTuple<F, Tuple, Seed, 0>
00623 {
00625 typedef Seed type;
00626 };
00627
00637 template<class Head, class Tail>
00638 struct JoinTuples
00639 {
00641 typedef typename ReduceTuple<PushBackTuple, Tail, Head>::type type;
00642 };
00643
00652 template<class Tuple>
00653 struct FlattenTuple
00654 {
00656 typedef typename ReduceTuple<JoinTuples, Tuple>::type type;
00657 };
00658
00660 }
00661
00662 #endif