Skip to content
Snippets Groups Projects
Commit 694083e1 authored by Carsten Gräser's avatar Carsten Gräser
Browse files

Add tuple utilities and corresponding tests

PushBackTuple to append a type
PushFrontTuple to prepend a type
JoinTuples to join two tuples
FlattenTuple to join several tuples contained in another tuple
ReduceTuple to apply a reduce transformation to a tuple as type containe

[[Imported from SVN: r6292]]
parent 5516b485
No related branches found
No related tags found
No related merge requests found
......@@ -26,4 +26,125 @@ dune_static_assert((Dune::FirstTypeIndex<MyTuple, double>::value == 2),
"FirstTypeIndex finds the wrong index for double in "
"MyTuple!");
//////////////////////////////////////////////////////////////////////
//
// check PushBackTuple
typedef Dune::PushBackTuple<MyTuple, char>::type MyTupleAppended1;
typedef Dune::tuple<int, unsigned, double, char> MyTupleAppended2;
dune_static_assert((Dune::is_same<MyTupleAppended1, MyTupleAppended2>::value),
"PushBackTuple failed!");
//////////////////////////////////////////////////////////////////////
//
// check PushFrontTuple
typedef Dune::PushFrontTuple<MyTuple, char>::type MyTuplePrepended1;
typedef Dune::tuple<char, int, unsigned, double> MyTuplePrepended2;
dune_static_assert((Dune::is_same<MyTuplePrepended1, MyTuplePrepended2>::value),
"PushFrontTuple failed!");
//////////////////////////////////////////////////////////////////////
//
// check JoinTuples
typedef Dune::JoinTuples<MyTuple, MyTuple>::type MyTupleMyTuple1;
typedef Dune::tuple<int, unsigned, double, int, unsigned, double> MyTupleMyTuple2;
dune_static_assert((Dune::is_same<MyTupleMyTuple1, MyTupleMyTuple2>::value),
"JoinTuples failed!");
//////////////////////////////////////////////////////////////////////
//
// check FlattenTuple
typedef Dune::tuple<char, float> MyTuple2;
typedef Dune::tuple<MyTuple, MyTuple2> MyTupleTuple;
typedef Dune::FlattenTuple<MyTupleTuple>::type MyTupleTupleFlat1;
typedef Dune::tuple<int, unsigned, double, char, float> MyTupleTupleFlat2;
dune_static_assert((Dune::is_same<MyTupleTupleFlat1, MyTupleTupleFlat2>::value),
"FlattenTuples failed!");
//////////////////////////////////////////////////////////////////////
//
// check nested ReduceTuple with a litte TMP
// A tuple of a range of integers wrapped in integral_constant types
template<int start, int end>
struct Range
{
typedef typename Dune::PushBackTuple<
typename Range<start, end-1>::type,
typename Dune::integral_constant<int,end-1>
>::type type;
};
template<int start>
struct Range<start, start>
{
typedef Dune::tuple<> type;
};
// An accumulator to build up a list of divisors of an integer using reduce
template<class Data, class PotentialDivisor>
struct DivisorAccumulator
{
enum {value = Data::first_type::value};
enum {isDivisor = (PotentialDivisor::value*(value / PotentialDivisor::value)==value)};
typedef typename Data::second_type OldTuple;
typedef typename Dune::PushBackTuple<OldTuple, PotentialDivisor>::type ExtendedTuple;
typedef typename Dune::SelectType<isDivisor, ExtendedTuple, OldTuple>::Type NewTuple;
typedef typename std::pair<typename Data::first_type, NewTuple> type;
};
// Construct list of divisors using reduce
template<int X>
struct Divisors
{
typedef typename Dune::ReduceTuple<
DivisorAccumulator,
typename Range<1,X+1>::type,
typename std::pair<typename Dune::integral_constant<int, X>, typename Dune::tuple<> >
>::type::second_type type;
enum {value = Dune::tuple_size<type>::value};
};
// An accumulator to build up a list of primes up to a fixed integer
template<class Data, class N>
struct PrimeAccumulator
{
enum {isPrime = (Divisors<N::value>::value==2)};
typedef typename Dune::SelectType<isPrime, typename Dune::PushBackTuple<Data, N>::type, Data>::Type type;
};
// Construct list primes
template<int X>
struct Primes
{
typedef typename Dune::ReduceTuple<
PrimeAccumulator,
typename Range<1,X+1>::type,
typename Dune::tuple<>
>::type type;
};
typedef Primes<9>::type Primes1;
typedef Dune::tuple<
Dune::integral_constant<int, 2>,
Dune::integral_constant<int, 3>,
Dune::integral_constant<int, 5>,
Dune::integral_constant<int, 7> > Primes2;
dune_static_assert((Dune::is_same<Primes1, Primes2>::value),
"ReduceTuple failed in primes-tmp!");
int main() {}
......@@ -1575,6 +1575,286 @@ namespace Dune {
struct FirstTypeIndex :
public FirstPredicateIndex<Tuple, IsType<T>::template Predicate, start>
{ };
/**
* \brief Helper template to append a type to a tuple
*
* \tparam Tuple The tuple type to extend
* \tparam T The type to be appended to the tuple
*
* With variadic templates the generic specialization would be:
*
\code
template<class... TupleArgs, class T>
struct PushBackTuple<typename Dune::tuple<TupleArgs...>, T>
{
typedef typename Dune::tuple<TupleArgs..., T> type;
};
\endcode
*
*/
template< class Tuple, class T>
struct PushBackTuple
{
dune_static_assert(AlwaysFalse<Tuple>::value, "Attempt to use the "
"unspecialized version of PushBackTuple. "
"PushBackTuple needs to be specialized for "
"each possible tuple size. Naturally the number of "
"pre-defined specializations is limited arbitrarily. "
"Maybe you need to raise this limit by defining some "
"more specializations?");
/**
* \brief For all specializations this is the type of a tuple with T appended.
*
* Suppose you have Tuple=tuple<T1, T2, ..., TN> then
* this type is tuple<T1, T2, ..., TN, T>.
*/
typedef Tuple type;
};
#ifndef DOXYGEN
template<class T>
struct PushBackTuple< Dune::tuple<>, T>
{
typedef typename Dune::tuple<T> type;
};
template< class T1, class T>
struct PushBackTuple< Dune::tuple<T1>, T>
{
typedef typename Dune::tuple<T1, T> type;
};
template< class T1, class T2, class T>
struct PushBackTuple< Dune::tuple<T1, T2>, T>
{
typedef typename Dune::tuple<T1, T2, T> type;
};
template< class T1, class T2, class T3, class T>
struct PushBackTuple< Dune::tuple<T1, T2, T3>, T>
{
typedef typename Dune::tuple<T1, T2, T3, T> type;
};
template< class T1, class T2, class T3, class T4, class T>
struct PushBackTuple< Dune::tuple<T1, T2, T3, T4>, T>
{
typedef typename Dune::tuple<T1, T2, T3, T4, T> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T>
struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5>, T>
{
typedef typename Dune::tuple<T1, T2, T3, T4, T5, T> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T6, class T>
struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5, T6>, T>
{
typedef typename Dune::tuple<T1, T2, T3, T4, T5, T6, T> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T>
struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7>, T>
{
typedef typename Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T>
struct PushBackTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8>, T>
{
typedef typename Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T> type;
};
#endif
/**
* \brief Helper template to prepend a type to a tuple
*
* \tparam Tuple The tuple type to extend
* \tparam T The type to be prepended to the tuple
*
* With variadic templates the generic specialization would be:
*
\code
template<class... TupleArgs, class T>
struct PushFrontTuple<typename Dune::tuple<TupleArgs...>, T>
{
typedef typename Dune::tuple<T, TupleArgs...> type;
};
\endcode
*
*/
template< class Tuple, class T>
struct PushFrontTuple
{
dune_static_assert(AlwaysFalse<Tuple>::value, "Attempt to use the "
"unspecialized version of PushFrontTuple. "
"PushFrontTuple needs to be specialized for "
"each possible tuple size. Naturally the number of "
"pre-defined specializations is limited arbitrarily. "
"Maybe you need to raise this limit by defining some "
"more specializations?");
/**
* \brief For all specializations this is the type of a tuple with T prepended.
*
* Suppose you have Tuple=tuple<T1, T2, ..., TN> then
* this type is tuple<T, T1, T2, ..., TN>.
*/
typedef Tuple type;
};
#ifndef DOXYGEN
template<class T>
struct PushFrontTuple< Dune::tuple<>, T>
{
typedef typename Dune::tuple<T> type;
};
template< class T1, class T>
struct PushFrontTuple< Dune::tuple<T1>, T>
{
typedef typename Dune::tuple<T, T1> type;
};
template< class T1, class T2, class T>
struct PushFrontTuple< Dune::tuple<T1, T2>, T>
{
typedef typename Dune::tuple<T, T1, T2> type;
};
template< class T1, class T2, class T3, class T>
struct PushFrontTuple< Dune::tuple<T1, T2, T3>, T>
{
typedef typename Dune::tuple<T, T1, T2, T3> type;
};
template< class T1, class T2, class T3, class T4, class T>
struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4>, T>
{
typedef typename Dune::tuple<T, T1, T2, T3, T4> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T>
struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5>, T>
{
typedef typename Dune::tuple<T, T1, T2, T3, T4, T5> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T6, class T>
struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5, T6>, T>
{
typedef typename Dune::tuple<T, T1, T2, T3, T4, T5, T6> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T>
struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7>, T>
{
typedef typename Dune::tuple<T, T1, T2, T3, T4, T5, T6, T7> type;
};
template< class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T>
struct PushFrontTuple< Dune::tuple<T1, T2, T3, T4, T5, T6, T7, T8>, T>
{
typedef typename Dune::tuple<T, T1, T2, T3, T4, T5, T6, T7, T8> type;
};
#endif
/**
* \brief Apply reduce with meta binary function to template
*
* For a tuple<T0,T1,...,TN-1,TN,...> the exported result is
*
* F< ... F< F< F<Seed,T0>::type, T1>::type, T2>::type, ... TN-1>::type
*
* \tparam F Binary meta function
* \tparam Tuple Apply reduce operation to this tuple
* \tparam Seed Initial value for reduce operation
* \tparan N Reduce the first N tuple elements
*/
template<
template <class, class> class F,
class Tuple,
class Seed=tuple<>,
int N=tuple_size<Tuple>::value>
struct ReduceTuple
{
typedef typename ReduceTuple<F, Tuple, Seed, N-1>::type Accumulated;
typedef typename tuple_element<N-1, Tuple>::type Value;
//! Result of the reduce operation
typedef typename F<Accumulated, Value>::type type;
};
/**
* \brief Apply reduce with meta binary function to template
*
* Specialization for reduction of 0 elements.
* The exported result type is Seed.
*
* \tparam F Binary meta function
* \tparam Tuple Apply reduce operation to this tuple
* \tparam Seed Initial value for reduce operation
*/
template<
template <class, class> class F,
class Tuple,
class Seed>
struct ReduceTuple<F, Tuple, Seed, 0>
{
//! Result of the reduce operation
typedef Seed type;
};
/**
* \brief Join two tuples
*
* For Head=tuple<T0,...,TN> and Tail=tuple<S0,...,SM>
* the exported result is tuple<T0,..,TN,S0,...,SM>.
*
* \tparam Head Head of resulting tuple
* \tparam Tail Tail of resulting tuple
*/
template<class Head, class Tail>
struct JoinTuples
{
//! Result of the join operation
typedef typename ReduceTuple< PushBackTuple, Tail, Head>::type type;
};
/**
* \brief Flatten a tuple of tuples
*
* This flattens a tuple of tuples tuple<tuple<T0,...,TN>, tuple<S0,...,SM> >
* and exports tuple<T0,..,TN,S0,...,SM>.
*
* \tparam TupleTuple A tuple of tuples
*/
template<class TupleTuple>
struct FlattenTuple
{
//! Result of the flatten operation
typedef typename ReduceTuple< JoinTuples, TupleTuple>::type type;
};
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment