diff lphobos/std/traits.d @ 94:61615fa85940 trunk

[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca"). Added support for array .sort and .reverse properties. Fixed some bugs with pointer arithmetic. Disabled some DMD AST optimizations that was messing things up, destroying valuable information. Added a KDevelop project file, this is what I use for coding LLVMDC now :) Other minor stuff.
author lindquist
date Mon, 12 Nov 2007 06:32:46 +0100
parents 42bf2eb2973b
children 373489eeaf90
line wrap: on
line diff
--- a/lphobos/std/traits.d	Thu Nov 08 19:21:05 2007 +0100
+++ b/lphobos/std/traits.d	Mon Nov 12 06:32:46 2007 +0100
@@ -1,15 +1,189 @@
+
+// Written in the D programming language.
+
+/**
+ * Templates with which to extract information about
+ * types at compile time.
+ *
+ * Macros:
+ *  WIKI = Phobos/StdTraits
+ * Copyright:
+ *  Public Domain
+ */
+
+/*
+ * Authors:
+ *  Walter Bright, Digital Mars, www.digitalmars.com
+ *  Tomasz Stachowiak (isStaticArray, isExpressionTuple)
+ */
+
 module std.traits;
-struct TypeHolder(S, T...) {
-  S _ReturnType;
-  T _ParameterTypeTuple;
+
+/***
+ * Get the type of the return value from a function,
+ * a pointer to function, or a delegate.
+ * Example:
+ * ---
+ * import std.traits;
+ * int foo();
+ * ReturnType!(foo) x;   // x is declared as int
+ * ---
+ */
+template ReturnType(alias dg)
+{
+    alias ReturnType!(typeof(dg)) ReturnType;
+}
+
+/** ditto */
+template ReturnType(dg)
+{
+    static if (is(dg R == return))
+    alias R ReturnType;
+    else
+    static assert(0, "argument has no return type");
+}
+
+/***
+ * Get the types of the paramters to a function,
+ * a pointer to function, or a delegate as a tuple.
+ * Example:
+ * ---
+ * import std.traits;
+ * int foo(int, long);
+ * void bar(ParameterTypeTuple!(foo));      // declares void bar(int, long);
+ * void abc(ParameterTypeTuple!(foo)[1]);   // declares void abc(long);
+ * ---
+ */
+template ParameterTypeTuple(alias dg)
+{
+    alias ParameterTypeTuple!(typeof(dg)) ParameterTypeTuple;
+}
+
+/** ditto */
+template ParameterTypeTuple(dg)
+{
+    static if (is(dg P == function))
+    alias P ParameterTypeTuple;
+    else static if (is(dg P == delegate))
+    alias ParameterTypeTuple!(P) ParameterTypeTuple;
+    else static if (is(dg P == P*))
+    alias ParameterTypeTuple!(P) ParameterTypeTuple;
+    else
+    static assert(0, "argument has no parameters");
+}
+
+
+/***
+ * Get the types of the fields of a struct or class.
+ * This consists of the fields that take up memory space,
+ * excluding the hidden fields like the virtual function
+ * table pointer.
+ */
+
+template FieldTypeTuple(S)
+{
+    static if (is(S == struct) || is(S == class))
+    alias typeof(S.tupleof) FieldTypeTuple;
+    else
+    static assert(0, "argument is not struct or class");
 }
-TypeHolder!(S, T) *IFTI_gen(S, T...)(S delegate(T) dg) { return null; }
-TypeHolder!(S, T) *IFTI_gen(S, T...)(S function(T) dg) { return null; }
-template ParameterTypeTuple(T) {
-  alias typeof(IFTI_gen(T.init)._ParameterTypeTuple) ParameterTypeTuple;
+
+
+/***
+ * Get a TypeTuple of the base class and base interfaces of
+ * this class or interface.
+ * Example:
+ * ---
+ * import std.traits, std.typetuple, std.stdio;
+ * interface I { }
+ * class A { }
+ * class B : A, I { }
+ *
+ * void main()
+ * {
+ *     alias BaseTypeTuple!(B) TL;
+ *     writefln(typeid(TL));    // prints: (A,I)
+ * }
+ * ---
+ */
+
+template BaseTypeTuple(A)
+{
+    static if (is(A P == super))
+    alias P BaseTypeTuple;
+    else
+    static assert(0, "argument is not a class or interface");
+}
+
+unittest
+{
+    interface I { }
+    class A { }
+    class B : A, I { }
+
+    alias BaseTypeTuple!(B) TL;
+    assert(TL.length == 2);
+    assert(is (TL[0] == A));
+    assert(is (TL[1] == I));
 }
-template ReturnType(T) {
-  alias typeof(IFTI_gen(T.init)._ReturnType) ReturnType;
+
+/* *******************************************
+ */
+template isStaticArray_impl(T)
+{
+    const T inst = void;
+    
+    static if (is(typeof(T.length)))
+    {
+    static if (!is(typeof(T) == typeof(T.init)))
+    {           // abuses the fact that int[5].init == int
+        static if (is(T == typeof(T[0])[inst.length]))
+        {   // sanity check. this check alone isn't enough because dmd complains about dynamic arrays
+        const bool res = true;
+        }
+        else
+        const bool res = false;
+    }
+    else
+        const bool res = false;
+    }
+    else
+    {
+        const bool res = false;
+    }
 }
-template isArray(T) { const bool isArray=false; }
-template isArray(T: T[]) { const bool isArray=true; }
+/**
+ * Detect whether type T is a static array.
+ */
+template isStaticArray(T)
+{
+    const bool isStaticArray = isStaticArray_impl!(T).res;
+}
+
+
+static assert (isStaticArray!(int[51]));
+static assert (isStaticArray!(int[][2]));
+//static assert (isStaticArray!(char[][int][11]));
+static assert (!isStaticArray!(int[]));
+//static assert (!isStaticArray!(int[char]));
+static assert (!isStaticArray!(int[1][]));
+
+template isArray(T)
+{
+    const bool isArray=false;
+}
+template isArray(T: T[])
+{
+    const bool isArray=true;
+}
+
+/**
+ * Tells whether the tuple T is an expression tuple.
+ */
+template isExpressionTuple(T ...)
+{
+    static if (is(void function(T)))
+    const bool isExpressionTuple = false;
+    else
+    const bool isExpressionTuple = true;
+}