Index: std/typetuple.d
===================================================================
--- std/typetuple.d	(revision 16)
+++ std/typetuple.d	(working copy)
@@ -26,6 +26,8 @@
 
 module std.typetuple;
 
+import std.traits;
+
 /**
  * Creates a typetuple out of a sequence of zero or more types.
  * Example:
@@ -51,7 +53,382 @@
     alias TList TypeTuple;
 }
 
+
 /**
+$(D PackedTuple!(T)) packs a static tuple $(D T) into a single template
+instance.
+
+Examples:
+--------------------
+// Make a nested tuple.
+alias TypeTuple!(PackedTuple!( byte,  ubyte),
+                 PackedTuple!(short, ushort)) Types;
+alias Types[0] X;
+alias Types[1] Y;
+static assert(is(X.unpack == TypeTuple!( byte,  ubyte)));
+static assert(is(Y.unpack == TypeTuple!(short, ushort)));
+
+// Compare two tuples.
+alias TypeTuple!(1, 2, 3, 4, 5) A;
+alias TypeTuple!(5, 4, 3, 2, 1) B;
+static assert(PackedTuple!(A).equals!(B) == false);
+static assert(PackedTuple!(A).consistsOf!(B) == true);
+--------------------
+ */
+template PackedTuple(T...)
+{
+    /**
+     * Expands the packed tuple $(D T).
+     */
+    alias T unpack;
+
+    /**
+     * Defined to be the number of elements in the packed tuple, namely
+     * $(D T._length).
+     */
+    enum size_t length = T.length;
+
+
+    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
+
+    /**
+     * Returns true if $(D T) and $(D U) are identical, or false
+     * otherwise.
+     */
+    template equals(U...)
+    {
+        static if (T.length == U.length)
+        {
+            static if (T.length == 0)
+                enum equals = true;
+            else static if (isSame!(T[0], U[0]))
+                enum equals = PackedTuple!(T[1 .. $])
+                    .equals!(U[1 .. $]);
+            else
+                enum equals = false;
+        }
+        else
+        {
+            enum equals = false;
+        }
+    }
+
+    /**
+     * Returns true if $(D T) and $(D U) are identical, regardless of
+     * the order of elements; or returns false otherwise.
+     */
+    template consistsOf(U...)
+    {
+        static if (T.length == U.length)
+        {
+            static if (T.length == 0)
+                enum consistsOf = true;
+            else
+                enum consistsOf = PackedTuple!(Erase!(U[0], T))
+                    .consistsOf!(U[1 .. $]);
+        }
+        else
+        {
+            enum consistsOf = false;
+        }
+    }
+}
+
+unittest
+{
+    alias PackedTuple!() E;
+    static assert( E.equals!());
+    static assert(!E.equals!(0));
+    static assert( E.consistsOf!());
+    static assert(!E.consistsOf!(0));
+
+    alias PackedTuple!(1, int, "abc") P;
+    static assert( P.equals!(1, int, "abc"));
+    static assert(!P.equals!("abc", 1, int));
+    static assert(!P.equals!(int, "abc", 1));
+    static assert(!P.equals!(1, int, "cba"));
+    static assert(!P.equals!());
+    static assert( P.consistsOf!(1, int, "abc"));
+    static assert( P.consistsOf!("abc", 1, int));
+    static assert( P.consistsOf!(int, "abc", 1));
+    static assert(!P.consistsOf!(1, int, "cba"));
+    static assert(!P.consistsOf!());
+}
+
+
+/**
+Builds an array from an expression tuple of constant values $(D lst).
+The common type deduced from $(D typeof(lst)) is used for the element
+type.
+
+Example:
+--------------------
+enum a = tupleToArray!(3, 1.0F, 4.0, 1u);
+static assert(a == [ 3.0, 1.0, 4.0, 1.0 ]);
+--------------------
+ */
+template tupleToArray(lst...)
+    if (lst.length >= 1)
+{
+    static assert(isExpressionTuple!(lst), "not an expression tuple");
+
+    enum tupleToArray =
+        tupleToArrayImpl!(CommonType!(typeof(lst)), lst).result;
+}
+
+// [internal]
+private template tupleToArrayImpl(T, lst...)
+{
+    static assert(!is(T == void), "cannot deduce common type");
+
+    static if (lst.length == 1)
+        enum T[] result = [ cast(T) lst[0] ];
+    else
+        enum T[] result =
+            tupleToArrayImpl!(T, lst[0 .. $ - 1]).result ~
+            cast(T) lst[$ - 1];
+}
+
+unittest
+{
+    enum a = tupleToArray!(3, 1.0F, 4.0, 1u);
+    static assert(a == [ 3.0, 1.0, 4.0, 1.0 ]);
+}
+
+
+/**
+Expands all elements in the array literal $(D arr) into a static tuple.
+
+Example:
+--------------------
+enum a = [ 2, 7, 1, 8 ];
+alias arrayToTuple!(a) A;
+static assert(PackedTuple!(A).equals!(2, 7, 1, 8));
+--------------------
+ */
+template arrayToTuple(alias arr)
+{
+    static if (arr.length)
+        alias TypeTuple!(arr[0], arrayToTuple!(arr[1 .. $]))
+            arrayToTuple;
+    else
+        alias TypeTuple!() arrayToTuple;
+}
+
+unittest
+{
+    enum a = [ 2, 7, 1, 8 ];
+    alias arrayToTuple!(a) A;
+    static assert(PackedTuple!(A).equals!(2, 7, 1, 8));
+}
+
+
+/**
+$(D staticFilter!(pred, lst)) returns a static tuple consisting only of
+elements in $(D lst) satisfying the predicate $(D pred).
+
+Example:
+--------------------
+template isNegative(int n) { enum isNegative = (n < 0); }
+
+alias staticFilter!(isNegative, -2, 4, 3, -1, 0) F;
+static assert(F.length == 2);
+static assert(F[0] == -2);
+static assert(F[1] == -1);
+--------------------
+ */
+template staticFilter(alias pred, lst...)
+{
+    alias staticPartition!(pred, lst).take staticFilter;
+}
+
+unittest
+{
+    struct Scope
+    {
+        template isNegative(int n) { enum isNegative = (n < 0); }
+
+        alias staticFilter!(isNegative, -2, 4, 3, -1, 0) L;
+        static assert(L.length == 2);
+        static assert(L[0] == -2);
+        static assert(L[1] == -1);
+    }
+}
+
+
+/**
+$(D staticPartition!(pred, lst)) returns two static tuples $(D .take)
+and $(D .drop). $(D take) consists only of elements in $(D lst)
+satisfying the predicate $(D pred), and $(D drop) consists of the rest.
+The order of the elements is preserved.
+
+Example:
+--------------------
+alias staticPartition!(isIntegral, string, short, void*, int) P;
+static assert(is(P.take == TypeTuple!(short, int)));
+static assert(is(P.drop == TypeTuple!(string, void*)));
+--------------------
+ */
+template staticPartition(alias pred, lst...)
+{
+    static if (lst.length)
+        alias partitionSub!(pred, lst).result staticPartition;
+    else
+        alias staticPartitionResult!(0) staticPartition;
+}
+
+private template staticPartitionResult(size_t i, lst...)
+{
+    alias lst[0 .. i] take;
+    alias lst[i .. $] drop;
+
+private:
+    alias lst all;
+    enum  at = i;
+}
+
+// [internal]
+private template partitionSub(alias pred, lst...)
+    if (lst.length)
+{
+    alias staticPartition!(pred, lst[1 .. $]) n;
+
+    static if (pred!(lst[0]))
+        alias staticPartitionResult!(
+                n.at + 1, lst[0], n.all) result;
+    else
+        alias staticPartitionResult!(
+                n.at, n.take, lst[0], n.drop) result;
+}
+
+unittest
+{
+    struct Scope
+    {
+        template isSigned(T) { enum isSigned = (T.min < 0); }
+        alias staticPartition!(isSigned) p1;
+        static assert(p1.take.length == 0);
+        static assert(p1.drop.length == 0);
+        alias staticPartition!(isSigned, uint, short, ushort, int) p2;
+        static assert(is(p2.take == TypeTuple!(short, int)));
+        static assert(is(p2.drop == TypeTuple!(uint, ushort)));
+    }
+}
+
+
+/**
+See $(XREF algorithm, reduce).
+
+Example:
+--------------------
+template Larger(A, B)
+{
+    static if (A.sizeof >= B.sizeof)
+        alias A Larger;
+    else
+        alias B Larger;
+}
+alias staticReduce!(Larger, byte, int, long, short) Largest;
+static assert(is(Largest == long));
+--------------------
+ */
+template staticReduce(alias fun, seed, lst...)
+{
+    alias genericStaticReduce!(fun, seed, lst) staticReduce;
+}
+
+/// Ditto
+template staticReduce(alias fun, alias seed, lst...)
+{
+    alias genericStaticReduce!(fun, seed, lst) staticReduce;
+}
+
+// [internal]
+private template genericStaticReduce(alias fun, lst...)
+    if (lst.length >= 1)
+{
+    static if (lst.length > 1)
+        alias genericStaticReduce!(fun,
+                fun!(lst[0], lst[1]), lst[2 .. $])
+            genericStaticReduce;
+    else
+        alias Alias!(lst[0]) genericStaticReduce;
+}
+
+unittest
+{
+    struct Scope
+    {
+        template Larger(A, B)
+        {
+            static if (A.sizeof >= B.sizeof)
+                alias A Larger;
+            else
+                alias B Larger;
+        }
+        alias staticReduce!(Larger, byte, int, long, short) Largest;
+        static assert(is(Largest == long));
+    }
+}
+
+
+/**
+Evaluates to $(D TypeTuple!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
+
+Example:
+----
+alias staticMap!(Unqual, int, const int, immutable int) T;
+static assert(is(T == TypeTuple!(int, int, int)));
+----
+ */
+template staticMap(alias F, T...)
+{
+    static if (T.length == 0)
+    {
+        alias TypeTuple!() staticMap;
+    }
+    else
+    {
+        alias TypeTuple!(F!(T[0]), staticMap!(F, T[1 .. $])) staticMap;
+    }
+}
+
+unittest
+{
+    alias staticMap!(Unqual, int, const int, immutable int) T;
+    static assert(is(T == TypeTuple!(int, int, int)));
+}
+
+/**
+Evaluates to $(D F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1])).
+
+Example:
+----
+static assert(!allSatisfy!(isIntegral, int, double));
+static assert(allSatisfy!(isIntegral, int, long));
+----
+ */
+template allSatisfy(alias F, T...)
+    if (T.length >= 1)
+{
+    static if (T.length == 1)
+    {
+        alias F!(T[0]) allSatisfy;
+    }
+    else
+    {
+        enum bool allSatisfy = F!(T[0]) && allSatisfy!(F, T[1 .. $]);
+    }
+}
+
+unittest
+{
+    static assert(!allSatisfy!(isIntegral, int, double));
+    static assert(allSatisfy!(isIntegral, int, long));
+}
+
+
+/**
  * Returns the index of the first occurrence of type T in the
  * sequence of zero or more types TList.
  * If not found, -1 is returned.
@@ -179,11 +556,11 @@
 
 unittest
 {
-    static assert(Pack!(Erase!(int,
+    static assert(PackedTuple!(Erase!(int,
                 short, int, int, 4)).
         equals!(short,      int, 4));
 
-    static assert(Pack!(Erase!(1,
+    static assert(PackedTuple!(Erase!(1,
                 real, 3, 1, 4, 1, 5, 9)).
         equals!(real, 3,    4, 1, 5, 9));
 }
@@ -237,11 +614,11 @@
 
 unittest
 {
-    static assert(Pack!(EraseAll!(int,
+    static assert(PackedTuple!(EraseAll!(int,
                 short, int, int, 4)).
         equals!(short,           4));
 
-    static assert(Pack!(EraseAll!(1,
+    static assert(PackedTuple!(EraseAll!(1,
                 real, 3, 1, 4, 1, 5, 9)).
         equals!(real, 3,    4,    5, 9));
 }
@@ -268,7 +645,7 @@
 
 unittest
 {
-    static assert(Pack!(
+    static assert(PackedTuple!(
         NoDuplicates!(1, int, 1, NoDuplicates, int, NoDuplicates, real))
              .equals!(1, int,    NoDuplicates,                    real));
 }
@@ -335,19 +712,19 @@
 
 unittest
 {
-    static assert(Pack!(Replace!(byte, ubyte,
+    static assert(PackedTuple!(Replace!(byte, ubyte,
                 short,  byte, byte, byte)).
         equals!(short, ubyte, byte, byte));
 
-    static assert(Pack!(Replace!(1111, byte,
+    static assert(PackedTuple!(Replace!(1111, byte,
                 2222, 1111, 1111, 1111)).
         equals!(2222, byte, 1111, 1111));
 
-    static assert(Pack!(Replace!(byte, 1111,
+    static assert(PackedTuple!(Replace!(byte, 1111,
                 short, byte, byte, byte)).
         equals!(short, 1111, byte, byte));
 
-    static assert(Pack!(Replace!(1111, "11",
+    static assert(PackedTuple!(Replace!(1111, "11",
                 2222, 1111, 1111, 1111)).
         equals!(2222, "11", 1111, 1111));
 }
@@ -415,19 +792,19 @@
 
 unittest
 {
-    static assert(Pack!(ReplaceAll!(byte, ubyte,
+    static assert(PackedTuple!(ReplaceAll!(byte, ubyte,
                  byte, short,  byte,  byte)).
         equals!(ubyte, short, ubyte, ubyte));
 
-    static assert(Pack!(ReplaceAll!(1111, byte,
+    static assert(PackedTuple!(ReplaceAll!(1111, byte,
                 1111, 2222, 1111, 1111)).
         equals!(byte, 2222, byte, byte));
 
-    static assert(Pack!(ReplaceAll!(byte, 1111,
+    static assert(PackedTuple!(ReplaceAll!(byte, 1111,
                 byte, short, byte, byte)).
         equals!(1111, short, 1111, 1111));
 
-    static assert(Pack!(ReplaceAll!(1111, "11",
+    static assert(PackedTuple!(ReplaceAll!(1111, "11",
                 1111, 2222, 1111, 1111)).
         equals!("11", 2222, "11", "11"));
 }
@@ -503,7 +880,6 @@
 
 
 // : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : //
-private:
 
 /*
  * [internal] With the builtin alias declaration, you cannot declare
@@ -522,8 +898,8 @@
         else
             static assert(0, "Cannot alias " ~ a.stringof);
     }
-    // types and tuples
-    template Alias(a...)
+    // type
+    template Alias(a)
     {
         alias a Alias;
     }
@@ -535,7 +911,6 @@
     static assert(__traits(compiles, { alias Alias!(123) a; }));
     static assert(__traits(compiles, { alias Alias!(abc) a; }));
     static assert(__traits(compiles, { alias Alias!(int) a; }));
-    static assert(__traits(compiles, { alias Alias!(1,abc,int) a; }));
 }
 
 
@@ -615,34 +990,3 @@
     static assert( isSame!(z, z));
 }
 
-/*
- * [internal] Confines a tuple within a template.
- */
-private template Pack(T...)
-{
-    alias T tuple;
-
-    // For convenience
-    template equals(U...)
-    {
-        static if (T.length == U.length)
-        {
-            static if (T.length == 0)
-                enum equals = true;
-            else
-                enum equals = isSame!(T[0], U[0]) &&
-                    Pack!(T[1 .. $]).equals!(U[1 .. $]);
-        }
-        else
-        {
-            enum equals = false;
-        }
-    }
-}
-
-unittest
-{
-    static assert( Pack!(1, int, "abc").equals!(1, int, "abc"));
-    static assert(!Pack!(1, int, "abc").equals!(1, int, "cba"));
-}
-
Index: std/traits.d
===================================================================
--- std/traits.d	(revision 15)
+++ std/traits.d	(working copy)
@@ -1118,60 +1118,6 @@
 }
 
 /**
-Evaluates to $(D TypeTuple!(F[T[0]], F[T[1]], ..., F[T[$ - 1]])).
-
-Example:
-----
-alias staticMap!(Unqual, int, const int, immutable int) T;
-static assert(is(T == TypeTuple!(int, int, int)));
-----
- */
-template staticMap(alias F, T...)
-{
-    static if (T.length == 1)
-    {
-        alias F!(T[0]) staticMap;
-    }
-    else
-    {
-        alias TypeTuple!(F!(T[0]), staticMap!(F, T[1 .. $])) staticMap;
-    }
-}
-
-unittest
-{
-    alias staticMap!(Unqual, int, const int, immutable int) T;
-    static assert(is(T == TypeTuple!(int, int, int)));
-}
-
-/**
-Evaluates to $(D F[T[0]] && F[T[1]] && ... && F[T[$ - 1]]).
-
-Example:
-----
-static assert(!allSatisfy!(isIntegral, int, double));
-static assert(allSatisfy!(isIntegral, int, long));
-----
- */
-template allSatisfy(alias F, T...)
-{
-    static if (T.length == 1)
-    {
-        alias F!(T[0]) allSatisfy;
-    }
-    else
-    {
-        enum bool allSatisfy = F!(T[0]) && allSatisfy!(F, T[1 .. $]);
-    }
-}
-
-unittest
-{
-    static assert(!allSatisfy!(isIntegral, int, double));
-    static assert(allSatisfy!(isIntegral, int, long));
-}
-
-/**
 Aliases itself to $(D T) if the boolean $(D condition) is $(D true)
 and to $(D F) otherwise.
 
