Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
607 lines (478 sloc) 11.7 KB
Ddoc
$(SPEC_S Traits,
$(P Traits are extensions to the language to enable
programs, at compile time, to get at information
internal to the compiler. This is also known as
compile time reflection.
It is done as a special, easily extended syntax (similar
to Pragmas) so that new capabilities can be added
as required.
)
$(GRAMMAR
$(GNAME TraitsExpression):
$(B __traits) $(B $(LPAREN)) $(I TraitsKeyword) $(B ,) $(I TraitsArguments) $(B $(RPAREN))
$(GNAME TraitsKeyword):
$(B isAbstractClass)
$(B isArithmetic)
$(B isAssociativeArray)
$(B isFinalClass)
$(B isFloating)
$(B isIntegral)
$(B isScalar)
$(B isStaticArray)
$(B isUnsigned)
$(B isVirtualFunction)
$(B isAbstractFunction)
$(B isFinalFunction)
$(V2 $(GBLINK isStaticFunction)
) $(GBLINK isRef)
$(GBLINK isOut)
$(GBLINK isLazy)
$(B hasMember)
$(V2 $(GBLINK identifier)
) $(B getMember)
$(V2 $(GBLINK getOverloads)
) $(GBLINK getVirtualFunctions)
$(B classInstanceSize)
$(GBLINK allMembers)
$(GBLINK derivedMembers)
$(B isSame)
$(B compiles)
$(GNAME TraitsArguments):
$(I TraitsArgument)
$(I TraitsArgument) $(B ,) $(I TraitsArguments)
$(GNAME TraitsArgument):
$(I AssignExpression)
$(I Type)
)
$(H2 isArithmetic)
$(P If the arguments are all either types that are arithmetic types,
or expressions that are typed as arithmetic types, then $(B true)
is returned.
Otherwise, $(B false) is returned.
If there are no arguments, $(B false) is returned.)
---
import std.stdio;
void main()
{
int i;
writefln(__traits(isArithmetic, int));
writefln(__traits(isArithmetic, i, i+1, int));
writefln(__traits(isArithmetic));
writefln(__traits(isArithmetic, int*));
}
---
$(P Prints:)
$(CONSOLE
true
true
false
false
)
$(H2 isFloating)
$(P Works like $(B isArithmetic), except it's for floating
point types (including imaginary and complex types).)
$(H2 isIntegral)
$(P Works like $(B isArithmetic), except it's for integral
types (including character types).)
$(H2 isScalar)
$(P Works like $(B isArithmetic), except it's for scalar
types.)
$(H2 isUnsigned)
$(P Works like $(B isArithmetic), except it's for unsigned
types.)
$(H2 isStaticArray)
$(P Works like $(B isArithmetic), except it's for static array
types.)
$(H2 isAssociativeArray)
$(P Works like $(B isArithmetic), except it's for associative array
types.)
$(H2 isAbstractClass)
$(P If the arguments are all either types that are abstract classes,
or expressions that are typed as abstract classes, then $(B true)
is returned.
Otherwise, $(B false) is returned.
If there are no arguments, $(B false) is returned.)
---
import std.stdio;
abstract class C { int foo(); }
void main()
{
C c;
writefln(__traits(isAbstractClass, C));
writefln(__traits(isAbstractClass, c, C));
writefln(__traits(isAbstractClass));
writefln(__traits(isAbstractClass, int*));
}
---
$(P Prints:)
$(CONSOLE
true
true
false
false
)
$(H2 isFinalClass)
$(P Works like $(B isAbstractClass), except it's for final
classes.)
$(H2 isVirtualFunction)
$(P Takes one argument. If that argument is a virtual function,
$(B true) is returned, otherwise $(B false).
)
---
import std.stdio;
struct S
{
void bar() { }
}
class C
{
void bar() { }
}
void main()
{
writefln(__traits(isVirtualFunction, C.bar)); // true
writefln(__traits(isVirtualFunction, S.bar)); // false
}
---
$(H2 isAbstractFunction)
$(P Takes one argument. If that argument is an abstract function,
$(B true) is returned, otherwise $(B false).
)
---
import std.stdio;
struct S
{
void bar() { }
}
class C
{
void bar() { }
}
class AC
{
abstract void foo();
}
void main()
{
writefln(__traits(isAbstractFunction, C.bar)); // false
writefln(__traits(isAbstractFunction, S.bar)); // false
writefln(__traits(isAbstractFunction, AC.foo)); // true
}
---
$(H2 isFinalFunction)
$(P Takes one argument. If that argument is a final function,
$(B true) is returned, otherwise $(B false).
)
---
import std.stdio;
struct S
{
void bar() { }
}
class C
{
void bar() { }
final void foo();
}
final class FC
{
void foo();
}
void main()
{
writefln(__traits(isFinalFunction, C.bar)); // false
writefln(__traits(isFinalFunction, S.bar)); // false
writefln(__traits(isFinalFunction, C.foo)); // true
writefln(__traits(isFinalFunction, FC.foo)); // true
}
---
$(V2
$(H2 $(GNAME isStaticFunction))
$(P Takes one argument. If that argument is a static function,
meaning it has no context pointer,
$(B true) is returned, otherwise $(B false).
)
)
$(H2 $(GNAME isRef), $(GNAME isOut), $(GNAME isLazy))
$(P Takes one argument. If that argument is a declaration,
$(B true) is returned if it is $(D_KEYWORD ref), $(D_KEYWORD out),
$(D_KEYWORD lazy), otherwise $(B false).
)
---
void fooref(ref int x)
{
static assert(__traits(isRef, x));
static assert(!__traits(isOut, x));
static assert(!__traits(isLazy, x));
}
void fooout(out int x)
{
static assert(!__traits(isRef, x));
static assert(__traits(isOut, x));
static assert(!__traits(isLazy, x));
}
void foolazy(lazy int x)
{
static assert(!__traits(isRef, x));
static assert(!__traits(isOut, x));
static assert(__traits(isLazy, x));
}
---
$(H2 hasMember)
$(P The first argument is a type that has members, or
is an expression of a type that has members.
The second argument is a string.
If the string is a valid property of the type,
$(B true) is returned, otherwise $(B false).
)
---
import std.stdio;
struct S
{
int m;
}
void main()
{ S s;
writefln(__traits(hasMember, S, "m")); // true
writefln(__traits(hasMember, s, "m")); // true
writefln(__traits(hasMember, S, "y")); // false
writefln(__traits(hasMember, int, "sizeof")); // true
}
---
$(V2
$(H2 $(GNAME identifier))
$(P Takes one argument, a symbol. Returns the identifier
for that symbol as a string literal.
)
)
$(H2 getMember)
$(P Takes two arguments, the second must be a string.
The result is an expression formed from the first
argument, followed by a $(SINGLEQUOTE .), followed by the second
argument as an identifier.
)
---
import std.stdio;
struct S
{
int mx;
static int my;
}
void main()
{ S s;
__traits(getMember, s, "mx") = 1; // same as s.mx=1;
writefln(__traits(getMember, s, "m" ~ "x")); // 1
__traits(getMember, S, "mx") = 1; // error, no this for S.mx
__traits(getMember, S, "my") = 2; // ok
}
---
$(V2
$(H2 $(GNAME getOverloads))
$(P The first argument is a class type or an expression of
class type.
The second argument is a string that matches the name of
one of the functions of that class.
The result is an array of all the overloads of that function.
)
---
import std.stdio;
class D
{
this() { }
~this() { }
void foo() { }
int foo(int) { return 2; }
}
void main()
{
D d = new D();
foreach (t; __traits(getOverloads, D, "foo"))
writefln(typeid(typeof(t)));
alias typeof(__traits(getOverloads, D, "foo")) b;
foreach (t; b)
writefln(typeid(t));
auto i = __traits(getOverloads, d, "foo")[1](1);
writefln(i);
}
---
$(P Prints:)
$(CONSOLE
void()
int()
void()
int()
2
)
)
$(H2 $(GNAME getVirtualFunctions))
$(P The first argument is a class type or an expression of
class type.
The second argument is a string that matches the name of
one of the functions of that class.
The result is an array of the virtual overloads of that function.
)
---
import std.stdio;
class D
{
this() { }
~this() { }
void foo() { }
int foo(int) { return 2; }
}
void main()
{
D d = new D();
foreach (t; __traits(getVirtualFunctions, D, "foo"))
writefln(typeid(typeof(t)));
alias typeof(__traits(getVirtualFunctions, D, "foo")) b;
foreach (t; b)
writefln(typeid(t));
auto i = __traits(getVirtualFunctions, d, "foo")[1](1);
writefln(i);
}
---
$(P Prints:)
$(CONSOLE
void()
int()
void()
int()
2
)
$(H2 classInstanceSize)
$(P Takes a single argument, which must evaluate to either
a class type or an expression of class type.
The result
is of type $(CODE size_t), and the value is the number of
bytes in the runtime instance of the class type.
It is based on the static type of a class, not the
polymorphic type.
)
$(H2 $(GNAME allMembers))
$(P Takes a single argument, which must evaluate to either
a type or an expression of type.
$(V1 An array)
$(V2 A tuple)
of string literals is returned, each of which
is the name of a member of that type combined with all
of the members of the base classes (if the type is a class).
No name is repeated.
Builtin properties are not included.
)
---
import std.stdio;
class D
{
this() { }
~this() { }
void foo() { }
int foo(int) { return 0; }
}
void main()
{
auto a = __traits(allMembers, D);
writefln(a);
$(V2 // _ctor,_dtor,foo,print,toString,toHash,opCmp,opEquals
auto b = [ __traits(allMembers, D) ];
writefln(b);
) // [_ctor,_dtor,foo,print,toString,toHash,opCmp,opEquals]
}
---
$(P The order in which the strings appear in the result
is not defined.)
$(H2 $(GNAME derivedMembers))
$(P Takes a single argument, which must evaluate to either
a type or an expression of type.
$(V1 An array)
$(V2 A tuple)
of string literals is returned, each of which
is the name of a member of that type.
No name is repeated.
Base class member names are not included.
Builtin properties are not included.
)
---
import std.stdio;
class D
{
this() { }
~this() { }
void foo() { }
int foo(int) { return 0; }
}
void main()
{
auto a = __traits(derivedMembers, D);
$(V1 writefln(a); // [_ctor,_dtor,foo])
$(V2 writefln(a); // _ctor,_dtor,foo)
}
---
$(P The order in which the strings appear in the result
is not defined.)
$(H2 isSame)
$(P Takes two arguments and returns bool $(B true) if they
are the same symbol, $(B false) if not.)
---
import std.stdio;
struct S { }
int foo();
int bar();
void main()
{
writefln(__traits(isSame, foo, foo)); // true
writefln(__traits(isSame, foo, bar)); // false
writefln(__traits(isSame, foo, S)); // false
writefln(__traits(isSame, S, S)); // true
writefln(__traits(isSame, std, S)); // false
writefln(__traits(isSame, std, std)); // true
}
---
$(P If the two arguments are expressions made up of literals
or enums that evaluate to the same value, true is returned.)
$(H2 compiles)
$(P Returns a bool $(B true) if all of the arguments
compile (are semantically correct).
The arguments can be symbols, types, or expressions that
are syntactically correct.
The arguments cannot be statements or declarations.
)
$(P If there are no arguments, the result is $(B false).)
---
import std.stdio;
struct S
{
static int s1;
int s2;
}
int foo();
int bar();
void main()
{
writefln(__traits(compiles)); // false
writefln(__traits(compiles, foo)); // true
writefln(__traits(compiles, foo + 1)); // true
writefln(__traits(compiles, &foo + 1)); // false
writefln(__traits(compiles, typeof(1))); // true
writefln(__traits(compiles, S.s1)); // true
writefln(__traits(compiles, S.s3)); // false
writefln(__traits(compiles, 1,2,3,int,long,std)); // true
writefln(__traits(compiles, 3[1])); // false
writefln(__traits(compiles, 1,2,3,int,long,3[1])); // false
}
---
$(P This is useful for:)
$(UL
$(LI Giving better error messages inside generic code than
the sometimes hard to follow compiler ones.)
$(LI Doing a finer grained specialization than template
partial specialization allows for.)
)
)
Macros:
TITLE=Traits
WIKI=Traits
CATEGORY_SPEC=$0
GBLINK=$(LINK2 #$0, $(B $0))
H2=<h2>$0</h2>