view tango/tango/core/Tuple.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
line wrap: on
line source

/**
 * The tuple module defines a template struct used for arbitrary data grouping.
 *
 * Copyright: Copyright (C) 2005-2006 Sean Kelly.  All rights reserved.
 * License:   BSD style: $(LICENSE)
 * Authors:   Walter Bright, Sean Kelly
 */
module tango.core.Tuple;


/**
 * A Tuple is a an aggregate of typed values.  Tuples are useful for returning
 * a set of values from a function or for passing a set of parameters to a
 * function.
 *
 * NOTE: Since the transition from user-defined to built-in tuples, the ability
 *       to return tuples from a function has been lost.  Until this issue is
 *       addressed within the language, tuples must be enclosed in a struct
 *       if they are to be returned from a function.
 *
 * Example:
 * ----------------------------------------------------------------------
 *
 * alias Tuple!(int, real) T1;
 * alias Tuple!(int, long) T2;
 * struct Wrap( Vals... )
 * {
 *     Vals val;
 * }
 *
 * Wrap!(T2) func( T1 val )
 * {
 *     Wrap!(T2) ret;
 *     ret.val[0] = val[0];
 *     ret.val[1] = val[0] * cast(long) val[1];
 *     return ret;
 * }
 *
 * ----------------------------------------------------------------------
 *
 * This is the original tuple example, and demonstates what should be possible
 * with tuples.  Hopefully, language support will be added for this feature
 * soon.
 *
 * Example:
 * ----------------------------------------------------------------------
 *
 * alias Tuple!(int, real) T1;
 * alias Tuple!(int, long) T2;
 *
 * T2 func( T1 val )
 * {
 *     T2 ret;
 *     ret[0] = val[0];
 *     ret[1] = val[0] * cast(long) val[1];
 *     return ret;
 * }
 *
 *
 * // tuples may be composed
 * alias Tuple!(int) IntTuple;
 * alias Tuple!(IntTuple, long) RetTuple;
 *
 * // tuples are equivalent to a set of function parameters of the same type
 * RetTuple t = func( 1, 2.3 );
 *
 * ----------------------------------------------------------------------
 */
template Tuple( TList... )
{
    alias TList Tuple;
}


/**
 * Returns the index of the first occurrence of T in TList or Tlist.length if
 * not found.
 */
template IndexOf( T, TList... )
{
    static if( TList.length == 0 )
        const size_t IndexOf = 0;
    else static if( is( T == TList[0] ) )
        const size_t IndexOf = 0;
    else
        const size_t IndexOf = 1 + IndexOf!( T, TList[1 .. $] );
}


/**
 * Returns a Tuple with the first occurrence of T removed from TList.
 */
template Remove( T, TList... )
{
    static if( TList.length == 0 )
        alias TList Remove;
    else static if( is( T == TList[0] ) )
        alias TList[1 .. $] Remove;
    else
        alias Tuple!( TList[0], Remove!( T, TList[1 .. $] ) ) Remove;
}


/**
 * Returns a Tuple with all occurrences of T removed from TList.
 */
template RemoveAll( T, TList... )
{
    static if( TList.length == 0 )
        alias TList RemoveAll;
    else static if( is( T == TList[0] ) )
        alias .RemoveAll!( T, TList[1 .. $] ) RemoveAll;
    else
        alias Tuple!( TList[0], .RemoveAll!( T, TList[1 .. $] ) ) RemoveAll;
}


/**
 * Returns a Tuple with the first offuccrence of T replaced with U.
 */
template Replace( T, U, TList... )
{
    static if( TList.length == 0 )
        alias TList Replace;
    else static if( is( T == TList[0] ) )
        alias Tuple!(U, TList[1 .. $]) Replace;
    else
        alias Tuple!( TList[0], Replace!( T, U, TList[1 .. $] ) ) Replace;
}


/**
 * Returns a Tuple with all occurrences of T replaced with U.
 */
template ReplaceAll( T, U, TList... )
{
    static if( TList.length == 0 )
        alias TList ReplaceAll;
    else static if( is( T == TList[0] ) )
        alias Tuple!( U, ReplaceAll!( T, U, TList[1 .. $] ) ) ReplaceAll;
    else
        alias Tuple!( TList[0], ReplaceAll!( T, U, TList[1 .. $] ) ) ReplaceAll;
}


/**
 * Returns a Tuple with the types from TList declared in reverse order.
 */
template Reverse( TList... )
{
    static if( TList.length == 0 )
        alias TList Reverse;
    else
        alias Tuple!( Reverse!( TList[1 .. $]), TList[0] ) Reverse;
}


/**
 * Returns a Tuple with all duplicate types removed.
 */
template Unique( TList... )
{
    static if( TList.length == 0 )
        alias TList Unique;
    else
        alias Tuple!( TList[0],
                      Unique!( RemoveAll!( TList[0],
                                           TList[1 .. $] ) ) ) Unique;
}


/**
 * Returns the type from TList that is the most derived from T.  If no such
 * type is found then T will be returned.
 */
template MostDerived( T, TList... )
{
    static if( TList.length == 0 )
        alias T MostDerived;
    else static if( is( TList[0] : T ) )
        alias MostDerived!( TList[0], TList[1 .. $] ) MostDerived;
    else
        alias MostDerived!( T, TList[1 .. $] ) MostDerived;
}


/**
 * Returns a Tuple with the types sorted so that the most derived types are
 * ordered before the remaining types.
 */
template DerivedToFront( TList... )
{
    static if( TList.length == 0 )
        alias TList DerivedToFront;
    else
        alias Tuple!( MostDerived!( TList[0], TList[1 .. $] ),
                      DerivedToFront!( ReplaceAll!( MostDerived!( TList[0], TList[1 .. $] ),
                                                    TList[0],
                                                    TList[1 .. $] ) ) ) DerivedToFront;
}


/*
 * A brief test of the above templates.
 */
static assert( 0 == IndexOf!(int, int, float, char));
static assert( 1 == IndexOf!(float, int, float, char));
static assert( 3 == IndexOf!(double, int, float, char));

static assert( is( Remove!(int, int, float, int) == Remove!(void, float, int) ) );
static assert( is( RemoveAll!(int, int, float, int) == Remove!(void, float) ) );
static assert( is( Remove!(float, int, float, int) == Remove!(void, int, int) ) );
static assert( is( Remove!(double, int, float, int) == Remove!(void, int, float, int) ) );

static assert( is( Replace!(int, char, int, float, int) == Remove!(void, char, float, int) ) );
static assert( is( ReplaceAll!(int, char, int, float, int) == Remove!(void, char, float, char) ) );
static assert( is( Replace!(float, char, int, float, int) == Remove!(void, int, char, int) ) );
static assert( is( Replace!(double, char, int, float, int) == Remove!(void, int, float, int) ) );

static assert( is( Reverse!(float, float[], double, char, int) ==
                   Unique!(int, char, double, float[], char, int, float, double) ) );

static assert( is( MostDerived!(int, long, short) == short ) );