Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

588 lines (452 sloc) 12.462 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)) $(GLINK TraitsKeyword) $(B ,) $(GLINK TraitsArguments) $(B $(RPAREN))
$(GNAME TraitsKeyword):
$(GBLINK isAbstractClass)
$(GBLINK isArithmetic)
$(GBLINK isAssociativeArray)
$(GBLINK isFinalClass)
$(GBLINK isFloating)
$(GBLINK isIntegral)
$(GBLINK isScalar)
$(GBLINK isStaticArray)
$(GBLINK isUnsigned)
$(GBLINK isVirtualFunction)
$(GBLINK isVirtualMethod)
$(GBLINK isAbstractFunction)
$(GBLINK isFinalFunction)
$(GBLINK isStaticFunction)
$(GBLINK isRef)
$(GBLINK isOut)
$(GBLINK isLazy)
$(GBLINK hasMember)
$(GBLINK identifier)
$(GBLINK getMember)
$(GBLINK getOverloads)
$(GBLINK getVirtualFunctions)
$(GBLINK getVirtualMethods)
$(GBLINK parent)
$(GBLINK classInstanceSize)
$(GBLINK allMembers)
$(GBLINK derivedMembers)
$(GBLINK isSame)
$(GBLINK compiles)
$(GNAME TraitsArguments):
$(GLINK TraitsArgument)
$(GLINK TraitsArgument) $(B ,) $(I TraitsArguments)
$(GNAME TraitsArgument):
$(GLINK2 expression, AssignExpression)
$(GLINK2 declaration, Type)
)
$(H2 $(GNAME 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;
writeln(__traits(isArithmetic, int));
writeln(__traits(isArithmetic, i, i+1, int));
writeln(__traits(isArithmetic));
writeln(__traits(isArithmetic, int*));
}
---
$(P Prints:)
$(CONSOLE
true
true
false
false
)
$(H2 $(GNAME isFloating))
$(P Works like $(B isArithmetic), except it's for floating
point types (including imaginary and complex types).)
$(H2 $(GNAME isIntegral))
$(P Works like $(B isArithmetic), except it's for integral
types (including character types).)
$(H2 $(GNAME isScalar))
$(P Works like $(B isArithmetic), except it's for scalar
types.)
$(H2 $(GNAME isUnsigned))
$(P Works like $(B isArithmetic), except it's for unsigned
types.)
$(H2 $(GNAME isStaticArray))
$(P Works like $(B isArithmetic), except it's for static array
types.)
$(H2 $(GNAME isAssociativeArray))
$(P Works like $(B isArithmetic), except it's for associative array
types.)
$(H2 $(GNAME 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;
writeln(__traits(isAbstractClass, C));
writeln(__traits(isAbstractClass, c, C));
writeln(__traits(isAbstractClass));
writeln(__traits(isAbstractClass, int*));
}
---
$(P Prints:)
$(CONSOLE
true
true
false
false
)
$(H2 $(GNAME isFinalClass))
$(P Works like $(B isAbstractClass), except it's for final
classes.)
$(H2 $(GNAME isVirtualFunction))
$(P The same as $(GLINK isVirtualMethod), except
that final functions that don't override anything return true.
)
$(H2 $(GNAME isVirtualMethod))
$(P Takes one argument. If that argument is a virtual function,
$(B true) is returned, otherwise $(B false).
Final functions that don't override anything return false.
)
---
import std.stdio;
struct S {
void bar() { }
}
class C {
void bar() { }
}
void main() {
writeln(__traits(isVirtualMethod, C.bar)); // true
writeln(__traits(isVirtualMethod, S.bar)); // false
}
---
$(H2 $(GNAME 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() {
writeln(__traits(isAbstractFunction, C.bar)); // false
writeln(__traits(isAbstractFunction, S.bar)); // false
writeln(__traits(isAbstractFunction, AC.foo)); // true
}
---
$(H2 $(GNAME 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() {
writeln(__traits(isFinalFunction, C.bar)); // false
writeln(__traits(isFinalFunction, S.bar)); // false
writeln(__traits(isFinalFunction, C.foo)); // true
writeln(__traits(isFinalFunction, FC.foo)); // true
}
---
$(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),
or $(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 $(GNAME 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;
writeln(__traits(hasMember, S, "m")); // true
writeln(__traits(hasMember, s, "m")); // true
writeln(__traits(hasMember, S, "y")); // false
writeln(__traits(hasMember, int, "sizeof")); // true
}
---
$(H2 $(GNAME identifier))
$(P Takes one argument, a symbol. Returns the identifier
for that symbol as a string literal.
)
$(H2 $(GNAME 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;
writeln(__traits(getMember, s, "m" ~ "x")); // 1
__traits(getMember, S, "mx") = 1; // error, no this for S.mx
__traits(getMember, S, "my") = 2; // ok
}
---
$(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 a tuple 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"))
writeln(typeid(typeof(t)));
alias typeof(__traits(getOverloads, D, "foo")) b;
foreach (t; b)
writeln(typeid(t));
auto i = __traits(getOverloads, d, "foo")[1](1);
writeln(i);
}
---
$(P Prints:)
$(CONSOLE
void()
int()
void()
int()
2
)
$(H2 $(GNAME getVirtualFunctions))
$(P The same as $(GLINK getVirtualMethods), except that
final functions that do not override anything are included.
)
$(H2 $(GNAME getVirtualMethods))
$(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 a tuple of the virtual overloads of that function.
It does not include final functions that do not override anything.
)
---
import std.stdio;
class D {
this() { }
~this() { }
void foo() { }
int foo(int) { return 2; }
}
void main() {
D d = new D();
foreach (t; __traits(getVirtualMethods, D, "foo"))
writeln(typeid(typeof(t)));
alias typeof(__traits(getVirtualMethods, D, "foo")) b;
foreach (t; b)
writeln(typeid(t));
auto i = __traits(getVirtualMethods, d, "foo")[1](1);
writeln(i);
}
---
$(P Prints:)
$(CONSOLE
void()
int()
void()
int()
2
)
$(H2 $(GNAME parent))
$(P Takes a single argument which must evaluate to a symbol.
The result is the symbol that is the parent of it.
)
$(H2 $(GNAME 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.
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 b = [ __traits(allMembers, D) ];
writeln(b);
// ["__ctor", "__dtor", "foo", "toString", "toHash", "opCmp", "opEquals", "Monitor", "factory"]
}
---
$(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.
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)];
writeln(a); // ["__ctor", "__dtor", "foo"]
}
---
$(P The order in which the strings appear in the result
is not defined.)
$(H2 $(GNAME 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() {
writeln(__traits(isSame, foo, foo)); // true
writeln(__traits(isSame, foo, bar)); // false
writeln(__traits(isSame, foo, S)); // false
writeln(__traits(isSame, S, S)); // true
writeln(__traits(isSame, std, S)); // false
writeln(__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 $(GNAME 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() {
writeln(__traits(compiles)); // false
writeln(__traits(compiles, foo)); // true
writeln(__traits(compiles, foo + 1)); // true
writeln(__traits(compiles, &foo + 1)); // false
writeln(__traits(compiles, typeof(1))); // true
writeln(__traits(compiles, S.s1)); // true
writeln(__traits(compiles, S.s3)); // false
writeln(__traits(compiles, 1,2,3,int,long,std)); // true
writeln(__traits(compiles, 3[1])); // false
writeln(__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>
Jump to Line
Something went wrong with that request. Please try again.