phobos/std/traits.d
2007-09-10 05:36:13 +00:00

183 lines
3.8 KiB
D

// 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;
/***
* 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");
}
/***
* 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 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;
}
}
/**
* 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][]));
/**
* 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;
}