Index: std/typetuple.d
===================================================================
--- std/typetuple.d	(revision 11)
+++ std/typetuple.d	(working copy)
@@ -70,20 +70,69 @@
  */
 template indexOf(T, TList...)
 {
-    static if (TList.length == 0)
-        enum int indexOf = -1;
-    else static if (is(T == TList[0]))
-        enum int indexOf = 0;
-    else
-        enum int indexOf =
-            (indexOf!(T, TList[1 .. length]) == -1)
-            ? -1
-            : 1 + indexOf!(T, TList[1 .. length]);
+    enum indexOf = genericIndexOf!(T, TList).index;
 }
 
+/// Ditto
+template indexOf(alias T, TList...)
+{
+    enum indexOf = genericIndexOf!(T, TList).index;
+}
+
 /// Kept for backwards compatibility
 alias indexOf IndexOf;
 
+// [internal]
+private template genericIndexOf(args...)
+    if (args.length >= 1)
+{
+    alias Alias!(args[0]) e;
+    alias   args[1 .. $]  tuple;
+
+    static if (tuple.length)
+    {
+        alias Alias!(tuple[0]) head;
+        alias   tuple[1 .. $]  tail;
+
+        static if (isSame!(e, head))
+        {
+            enum index = 0;
+        }
+        else
+        {
+            enum next  = genericIndexOf!(e, tail).index;
+            enum index = (next == -1) ? -1 : 1 + next;
+        }
+    }
+    else
+    {
+        enum index = -1;
+    }
+}
+
+unittest
+{
+    static assert(indexOf!( byte, byte, short, int, long) ==  0);
+    static assert(indexOf!(short, byte, short, int, long) ==  1);
+    static assert(indexOf!(  int, byte, short, int, long) ==  2);
+    static assert(indexOf!( long, byte, short, int, long) ==  3);
+    static assert(indexOf!( char, byte, short, int, long) == -1);
+    static assert(indexOf!(   -1, byte, short, int, long) == -1);
+    static assert(indexOf!(void) == -1);
+
+    static assert(indexOf!("abc", "abc", "def", "ghi", "jkl") ==  0);
+    static assert(indexOf!("def", "abc", "def", "ghi", "jkl") ==  1);
+    static assert(indexOf!("ghi", "abc", "def", "ghi", "jkl") ==  2);
+    static assert(indexOf!("jkl", "abc", "def", "ghi", "jkl") ==  3);
+    static assert(indexOf!("mno", "abc", "def", "ghi", "jkl") == -1);
+    static assert(indexOf!( void, "abc", "def", "ghi", "jkl") == -1);
+    static assert(indexOf!(42) == -1);
+
+    static assert(indexOf!(void, 0, "void", void) == 2);
+    static assert(indexOf!("void", 0, void, "void") == 2);
+}
+
+
 /**
  * Returns a typetuple created from TList with the first occurrence,
  * if any, of T removed.
@@ -96,14 +145,49 @@
  */
 template Erase(T, TList...)
 {
-    static if (TList.length == 0)
-	alias TList Erase;
-    else static if (is(T == TList[0]))
-	alias TList[1 .. length] Erase;
+    alias GenericErase!(T, TList).result Erase;
+}
+
+/// Ditto
+template Erase(alias T, TList...)
+{
+    alias GenericErase!(T, TList).result Erase;
+}
+
+// [internal]
+private template GenericErase(args...)
+    if (args.length >= 1)
+{
+    alias Alias!(args[0]) e;
+    alias   args[1 .. $]  tuple;
+
+    static if (tuple.length)
+    {
+        alias Alias!(tuple[0]) head;
+        alias   tuple[1 .. $]  tail;
+
+        static if (isSame!(e, head))
+            alias tail result;
+        else
+            alias TypeTuple!(head, GenericErase!(e, tail).result) result;
+    }
     else
-	alias TypeTuple!(TList[0], Erase!(T, TList[1 .. length])) Erase;
+    {
+        alias TypeTuple!() result;
+    }
 }
 
+unittest
+{
+    static assert(Pack!(Erase!(int,
+                short, int, int, 4)).
+        equals!(short,      int, 4));
+
+    static assert(Pack!(Erase!(1,
+                real, 3, 1, 4, 1, 5, 9)).
+        equals!(real, 3,    4, 1, 5, 9));
+}
+
 /**
  * Returns a typetuple created from TList with the all occurrences,
  * if any, of T removed.
@@ -118,14 +202,50 @@
  */
 template EraseAll(T, TList...)
 {
-    static if (TList.length == 0)
-	alias TList EraseAll;
-    else static if (is(T == TList[0]))
-	alias EraseAll!(T, TList[1 .. length]) EraseAll;
+    alias GenericEraseAll!(T, TList).result EraseAll;
+}
+
+/// Ditto
+template EraseAll(alias T, TList...)
+{
+    alias GenericEraseAll!(T, TList).result EraseAll;
+}
+
+// [internal]
+private template GenericEraseAll(args...)
+    if (args.length >= 1)
+{
+    alias Alias!(args[0]) e;
+    alias   args[1 .. $]  tuple;
+
+    static if (tuple.length)
+    {
+        alias Alias!(tuple[0]) head;
+        alias   tuple[1 .. $]  tail;
+        alias GenericEraseAll!(e, tail).result next;
+
+        static if (isSame!(e, head))
+            alias next result;
+        else
+            alias TypeTuple!(head, next) result;
+    }
     else
-	alias TypeTuple!(TList[0], EraseAll!(T, TList[1 .. length])) EraseAll;
+    {
+        alias TypeTuple!() result;
+    }
 }
 
+unittest
+{
+    static assert(Pack!(EraseAll!(int,
+                short, int, int, 4)).
+        equals!(short,           4));
+
+    static assert(Pack!(EraseAll!(1,
+                real, 3, 1, 4, 1, 5, 9)).
+        equals!(real, 3,    4,    5, 9));
+}
+
 /**
  * Returns a typetuple created from TList with the all duplicate
  * types removed.
@@ -146,6 +266,13 @@
 	alias TypeTuple!(TList[0], NoDuplicates!(EraseAll!(TList[0], TList[1 .. length]))) NoDuplicates;
 }
 
+unittest
+{
+    static assert(Pack!(
+        NoDuplicates!(1, int, 1, NoDuplicates, int, NoDuplicates, real))
+             .equals!(1, int,    NoDuplicates,                    real));
+}
+
 /**
  * Returns a typetuple created from TList with the first occurrence
  * of type T, if found, replaced with type U.
@@ -160,14 +287,72 @@
  */
 template Replace(T, U, TList...)
 {
-    static if (TList.length == 0)
-	alias TList Replace;
-    else static if (is(T == TList[0]))
-	alias TypeTuple!(U, TList[1 .. length]) Replace;
+    alias GenericReplace!(T, U, TList).result Replace;
+}
+
+/// Ditto
+template Replace(alias T, U, TList...)
+{
+    alias GenericReplace!(T, U, TList).result Replace;
+}
+
+/// Ditto
+template Replace(T, alias U, TList...)
+{
+    alias GenericReplace!(T, U, TList).result Replace;
+}
+
+/// Ditto
+template Replace(alias T, alias U, TList...)
+{
+    alias GenericReplace!(T, U, TList).result Replace;
+}
+
+// [internal]
+private template GenericReplace(args...)
+    if (args.length >= 2)
+{
+    alias Alias!(args[0]) from;
+    alias Alias!(args[1]) to;
+    alias   args[2 .. $]  tuple;
+
+    static if (tuple.length)
+    {
+        alias Alias!(tuple[0]) head;
+        alias    tuple[1 .. $] tail;
+
+        static if (isSame!(from, head))
+            alias TypeTuple!(to, tail) result;
+        else
+            alias TypeTuple!(head,
+                GenericReplace!(from, to, tail).result) result;
+    }
     else
-	alias TypeTuple!(TList[0], Replace!(T, U, TList[1 .. length])) Replace;
+    {
+        alias TypeTuple!() result;
+    }
 }
 
+unittest
+{
+    static assert(Pack!(Replace!(byte, ubyte,
+                short,  byte, byte, byte)).
+        equals!(short, ubyte, byte, byte));
+
+    static assert(Pack!(Replace!(1111, byte,
+                2222, 1111, 1111, 1111)).
+        equals!(2222, byte, 1111, 1111));
+
+    static assert(Pack!(Replace!(byte, 1111,
+                short, byte, byte, byte)).
+        equals!(short, 1111, byte, byte));
+
+    static assert(Pack!(Replace!(1111, "11",
+                2222, 1111, 1111, 1111)).
+        equals!(2222, "11", 1111, 1111));
+}
+
+
 /**
  * Returns a typetuple created from TList with all occurrences
  * of type T, if found, replaced with type U.
@@ -182,14 +367,72 @@
  */
 template ReplaceAll(T, U, TList...)
 {
-    static if (TList.length == 0)
-	alias TList ReplaceAll;
-    else static if (is(T == TList[0]))
-	alias TypeTuple!(U, ReplaceAll!(T, U, TList[1 .. length])) ReplaceAll;
+    alias GenericReplaceAll!(T, U, TList).result ReplaceAll;
+}
+
+/// Ditto
+template ReplaceAll(alias T, U, TList...)
+{
+    alias GenericReplaceAll!(T, U, TList).result ReplaceAll;
+}
+
+/// Ditto
+template ReplaceAll(T, alias U, TList...)
+{
+    alias GenericReplaceAll!(T, U, TList).result ReplaceAll;
+}
+
+/// Ditto
+template ReplaceAll(alias T, alias U, TList...)
+{
+    alias GenericReplaceAll!(T, U, TList).result ReplaceAll;
+}
+
+// [internal]
+private template GenericReplaceAll(args...)
+    if (args.length >= 2)
+{
+    alias Alias!(args[0]) from;
+    alias Alias!(args[1]) to;
+    alias   args[2 .. $]  tuple;
+
+    static if (tuple.length)
+    {
+        alias Alias!(tuple[0]) head;
+        alias    tuple[1 .. $] tail;
+        alias GenericReplaceAll!(from, to, tail).result next;
+
+        static if (isSame!(from, head))
+            alias TypeTuple!(to, next) result;
+        else
+            alias TypeTuple!(head, next) result;
+    }
     else
-	alias TypeTuple!(TList[0], ReplaceAll!(T, U, TList[1 .. length])) ReplaceAll;
+    {
+        alias TypeTuple!() result;
+    }
 }
 
+unittest
+{
+    static assert(Pack!(ReplaceAll!(byte, ubyte,
+                 byte, short,  byte,  byte)).
+        equals!(ubyte, short, ubyte, ubyte));
+
+    static assert(Pack!(ReplaceAll!(1111, byte,
+                1111, 2222, 1111, 1111)).
+        equals!(byte, 2222, byte, byte));
+
+    static assert(Pack!(ReplaceAll!(byte, 1111,
+                byte, short, byte, byte)).
+        equals!(1111, short, 1111, 1111));
+
+    static assert(Pack!(ReplaceAll!(1111, "11",
+                1111, 2222, 1111, 1111)).
+        equals!("11", 2222, "11", "11"));
+}
+
+
 /**
  * Returns a typetuple created from TList with the order reversed.
  * Example:
@@ -258,3 +501,148 @@
 						    TList[1 .. length]))) DerivedToFront;
 }
 
+
+// : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : //
+private:
+
+/*
+ * [internal] With the builtin alias declaration, you cannot declare
+ * aliases of, for example, literal values. You can alias anything
+ * including literal values via this template.
+ */
+private
+{
+    // symbols and literal values
+    template Alias(alias a)
+    {
+        static if (__traits(compiles, { alias a x; }))
+            alias a Alias;
+        else static if (__traits(compiles, { enum x = a; }))
+            enum Alias = a;
+        else
+            static assert(0, "Cannot alias " ~ a.stringof);
+    }
+    // types and tuples
+    template Alias(a...)
+    {
+        alias a Alias;
+    }
+}
+
+unittest
+{
+    enum abc = 1;
+    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; }));
+}
+
+
+/*
+ * [internal] Returns true if a and b are the same thing, or false if
+ * not. Both a and b can be types, literals, or symbols.
+ *
+ * How:                     When:
+ *      is(a == b)        - both are types
+ *        a == b          - both are literals (true literals, enums)
+ * __traits(isSame, a, b) - other cases (variables, functions,
+ *                          templates, etc.)
+ */
+private template isSame(ab...)
+    if (ab.length == 2)
+{
+    static if (__traits(compiles, expectType!(ab[0]),
+                                  expectType!(ab[1])))
+    {
+        enum isSame = is(ab[0] == ab[1]);
+    }
+    else static if (!__traits(compiles, expectType!(ab[0])) &&
+                    !__traits(compiles, expectType!(ab[1])) &&
+                     __traits(compiles, ab[0] == ab[1]))
+    {
+        static if (!__traits(compiles, &ab[0]) &&
+                   !__traits(compiles, &ab[1]))
+            enum isSame = (ab[0] == ab[1]);
+        else
+            enum isSame = __traits(isSame, ab[0], ab[1]);
+    }
+    else
+    {
+        enum isSame = __traits(isSame, ab[0], ab[1]);
+    }
+}
+private template expectType(T) {}
+
+unittest
+{
+    static assert( isSame!(int, int));
+    static assert(!isSame!(int, short));
+
+    enum a = 1, b = 1, c = 2;
+    static assert( isSame!(1, 1));
+    static assert( isSame!(a, 1));
+    static assert( isSame!(a, b));
+    static assert(!isSame!(b, c));
+    static assert(!isSame!(1, "1"));
+    static assert(!isSame!(a, "a"));
+    static assert( isSame!(isSame, isSame));
+    static assert(!isSame!(isSame, a));
+
+    static assert(!isSame!(byte, a));
+    static assert(!isSame!(short, isSame));
+    static assert(!isSame!(a, int));
+    static assert(!isSame!(long, isSame));
+
+    static immutable X = 1, Y = 1, Z = 2;
+    static assert( isSame!(X, X));
+    static assert(!isSame!(X, Y));
+    static assert(!isSame!(Y, Z));
+
+    int  foo();
+    int  bar();
+    real baz(int);
+    static assert( isSame!(foo, foo));
+    static assert(!isSame!(foo, bar));
+    static assert(!isSame!(bar, baz));
+    static assert( isSame!(baz, baz));
+
+    int  x, y;
+    real z;
+    static assert( isSame!(x, x));
+    static assert(!isSame!(x, y));
+    static assert(!isSame!(y, z));
+    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"));
+}
+
