1896 lines
49 KiB
Plaintext
1896 lines
49 KiB
Plaintext
Ddoc
|
|
|
|
$(SPEC_S Traits,
|
|
|
|
$(HEADERNAV_TOC)
|
|
|
|
$(H2 $(LNAME2 grammar, Grammar))
|
|
|
|
$(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):
|
|
$(D __traits) $(D $(LPAREN)) $(GLINK TraitsKeyword) $(D ,) $(GLINK TraitsArguments) $(D $(RPAREN))
|
|
|
|
$(GNAME TraitsKeyword):
|
|
$(RELATIVE_LINK2 isAbstractClass, $(D isAbstractClass))
|
|
$(RELATIVE_LINK2 isArithmetic, $(D isArithmetic))
|
|
$(RELATIVE_LINK2 isAssociativeArray, $(D isAssociativeArray))
|
|
$(RELATIVE_LINK2 isFinalClass, $(D isFinalClass))
|
|
$(RELATIVE_LINK2 isPOD, $(D isPOD))
|
|
$(RELATIVE_LINK2 isNested, $(D isNested))
|
|
$(RELATIVE_LINK2 isFuture, $(D isFuture))
|
|
$(RELATIVE_LINK2 isDeprecated, $(D isDeprecated))
|
|
$(RELATIVE_LINK2 isFloating, $(D isFloating))
|
|
$(RELATIVE_LINK2 isIntegral, $(D isIntegral))
|
|
$(RELATIVE_LINK2 isScalar, $(D isScalar))
|
|
$(RELATIVE_LINK2 isStaticArray, $(D isStaticArray))
|
|
$(RELATIVE_LINK2 isUnsigned, $(D isUnsigned))
|
|
$(RELATIVE_LINK2 isDisabled, $(D isDisabled))
|
|
$(RELATIVE_LINK2 isVirtualFunction, $(D isVirtualFunction))
|
|
$(RELATIVE_LINK2 isVirtualMethod, $(D isVirtualMethod))
|
|
$(RELATIVE_LINK2 isAbstractFunction, $(D isAbstractFunction))
|
|
$(RELATIVE_LINK2 isFinalFunction, $(D isFinalFunction))
|
|
$(RELATIVE_LINK2 isStaticFunction, $(D isStaticFunction))
|
|
$(RELATIVE_LINK2 isOverrideFunction, $(D isOverrideFunction))
|
|
$(RELATIVE_LINK2 isTemplate, $(D isTemplate))
|
|
$(RELATIVE_LINK2 isRef, $(D isRef))
|
|
$(RELATIVE_LINK2 isOut, $(D isOut))
|
|
$(RELATIVE_LINK2 isLazy, $(D isLazy))
|
|
$(RELATIVE_LINK2 isReturnOnStack, $(D isReturnOnStack))
|
|
$(RELATIVE_LINK2 isCopyable, $(D isCopyable))
|
|
$(RELATIVE_LINK2 isZeroInit, $(D isZeroInit))
|
|
$(RELATIVE_LINK2 isModule, $(D isModule))
|
|
$(RELATIVE_LINK2 isPackage, $(D isPackage))
|
|
$(RELATIVE_LINK2 hasMember, $(D hasMember))
|
|
$(RELATIVE_LINK2 hasCopyConstructor, $(D hasCopyConstructor))
|
|
$(RELATIVE_LINK2 hasPostblit, $(D hasPostblit))
|
|
$(RELATIVE_LINK2 identifier, $(D identifier))
|
|
$(RELATIVE_LINK2 getAliasThis, $(D getAliasThis))
|
|
$(RELATIVE_LINK2 getAttributes, $(D getAttributes))
|
|
$(RELATIVE_LINK2 getFunctionAttributes, $(D getFunctionAttributes))
|
|
$(RELATIVE_LINK2 getFunctionVariadicStyle, $(D getFunctionVariadicStyle))
|
|
$(RELATIVE_LINK2 getLinkage, $(D getLinkage))
|
|
$(RELATIVE_LINK2 getLocation, $(D getLocation))
|
|
$(RELATIVE_LINK2 getMember, $(D getMember))
|
|
$(RELATIVE_LINK2 getOverloads, $(D getOverloads))
|
|
$(RELATIVE_LINK2 getParameterStorageClasses, $(D getParameterStorageClasses))
|
|
$(RELATIVE_LINK2 getPointerBitmap, $(D getPointerBitmap))
|
|
$(RELATIVE_LINK2 getCppNamespaces, $(D getCppNamespaces))
|
|
$(RELATIVE_LINK2 getVisibility, $(D getVisibility))
|
|
$(RELATIVE_LINK2 getProtection, $(D getProtection))
|
|
$(RELATIVE_LINK2 getTargetInfo, $(D getTargetInfo))
|
|
$(RELATIVE_LINK2 getVirtualFunctions, $(D getVirtualFunctions))
|
|
$(RELATIVE_LINK2 getVirtualMethods, $(D getVirtualMethods))
|
|
$(RELATIVE_LINK2 getUnitTests, $(D getUnitTests))
|
|
$(RELATIVE_LINK2 parent, $(D parent))
|
|
$(RELATIVE_LINK2 child, $(D child))
|
|
$(RELATIVE_LINK2 classInstanceSize, $(D classInstanceSize))
|
|
$(RELATIVE_LINK2 classInstanceAlignment, $(D classInstanceAlignment))
|
|
$(RELATIVE_LINK2 getVirtualIndex, $(D getVirtualIndex))
|
|
$(RELATIVE_LINK2 allMembers, $(D allMembers))
|
|
$(RELATIVE_LINK2 derivedMembers, $(D derivedMembers))
|
|
$(RELATIVE_LINK2 isSame, $(D isSame))
|
|
$(RELATIVE_LINK2 compiles, $(D compiles))
|
|
$(RELATIVE_LINK2 toType, $(D toType))
|
|
$(RELATIVE_LINK2 initSymbol, $(D initSymbol))
|
|
$(RELATIVE_LINK2 parameters, $(D parameters))
|
|
|
|
$(GNAME TraitsArguments):
|
|
$(GLINK TraitsArgument)
|
|
$(GLINK TraitsArgument) $(D ,) $(GSELF TraitsArguments)
|
|
|
|
$(GNAME TraitsArgument):
|
|
$(GLINK2 expression, AssignExpression)
|
|
$(GLINK2 type, Type)
|
|
)
|
|
|
|
|
|
$(H2 $(LNAME2 types, Type Traits))
|
|
|
|
$(H3 $(GNAME isArithmetic))
|
|
|
|
$(P If the arguments are all either types that are arithmetic types,
|
|
or expressions that are typed as arithmetic types, then $(D true)
|
|
is returned.
|
|
Otherwise, $(D false) is returned.
|
|
If there are no arguments, $(D false) is returned.)
|
|
|
|
$(P Arithmetic types are integral types and floating point types.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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*));
|
|
}
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
true
|
|
true
|
|
false
|
|
false
|
|
)
|
|
|
|
$(H3 $(GNAME isFloating))
|
|
|
|
$(P If the arguments are all either types that are floating point types,
|
|
or expressions that are typed as floating point types, then $(D true)
|
|
is returned.
|
|
Otherwise, $(D false) is returned.
|
|
If there are no arguments, $(D false) is returned.)
|
|
|
|
$(P The floating point types are:
|
|
`float`, `double`, `real`,
|
|
`ifloat`, `idouble`, `ireal`,
|
|
`cfloat`, `cdouble`, `creal`,
|
|
vectors of floating point types, and enums with a floating point base type.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.simd : float4;
|
|
|
|
enum E : float { a, b }
|
|
|
|
static assert(__traits(isFloating, float));
|
|
static assert(__traits(isFloating, E));
|
|
static assert(__traits(isFloating, float4));
|
|
|
|
static assert(!__traits(isFloating, float[4]));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isIntegral))
|
|
|
|
$(P If the arguments are all either types that are integral types,
|
|
or expressions that are typed as integral types, then $(D true)
|
|
is returned.
|
|
Otherwise, $(D false) is returned.
|
|
If there are no arguments, $(D false) is returned.)
|
|
|
|
$(P The integral types are:
|
|
`byte`, `ubyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `cent`, `ucent`,
|
|
`bool`, `char`, `wchar`, `dchar`,
|
|
vectors of integral types, and enums with an integral base type.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.simd : int4;
|
|
|
|
enum E { a, b }
|
|
|
|
static assert(__traits(isIntegral, bool));
|
|
static assert(__traits(isIntegral, char));
|
|
static assert(__traits(isIntegral, int));
|
|
static assert(__traits(isIntegral, E));
|
|
static assert(__traits(isIntegral, int4));
|
|
|
|
static assert(!__traits(isIntegral, float));
|
|
static assert(!__traits(isIntegral, int[4]));
|
|
static assert(!__traits(isIntegral, void*));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isScalar))
|
|
|
|
$(P If the arguments are all either types that are scalar types,
|
|
or expressions that are typed as scalar types, then $(D true)
|
|
is returned.
|
|
Otherwise, $(D false) is returned.
|
|
If there are no arguments, $(D false) is returned.)
|
|
|
|
$(P Scalar types are integral types,
|
|
floating point types,
|
|
pointer types,
|
|
vectors of scalar types,
|
|
and enums with a scalar base type.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.simd : int4, void16;
|
|
|
|
enum E { a, b }
|
|
|
|
static assert(__traits(isScalar, bool));
|
|
static assert(__traits(isScalar, char));
|
|
static assert(__traits(isScalar, int));
|
|
static assert(__traits(isScalar, float));
|
|
static assert(__traits(isScalar, E));
|
|
static assert(__traits(isScalar, int4));
|
|
static assert(__traits(isScalar, void*)); // Includes pointers!
|
|
|
|
static assert(!__traits(isScalar, int[4]));
|
|
static assert(!__traits(isScalar, void16));
|
|
static assert(!__traits(isScalar, void));
|
|
static assert(!__traits(isScalar, typeof(null)));
|
|
static assert(!__traits(isScalar, Object));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isUnsigned))
|
|
|
|
$(P If the arguments are all either types that are unsigned types,
|
|
or expressions that are typed as unsigned types, then $(D true)
|
|
is returned.
|
|
Otherwise, $(D false) is returned.
|
|
If there are no arguments, $(D false) is returned.)
|
|
|
|
$(P The unsigned types are:
|
|
`ubyte`, `ushort`, `uint`, `ulong`, `ucent`,
|
|
`bool`, `char`, `wchar`, `dchar`,
|
|
vectors of unsigned types, and enums with an unsigned base type.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.simd : uint4;
|
|
|
|
enum SignedEnum { a, b }
|
|
enum UnsignedEnum : uint { a, b }
|
|
|
|
static assert(__traits(isUnsigned, bool));
|
|
static assert(__traits(isUnsigned, char));
|
|
static assert(__traits(isUnsigned, uint));
|
|
static assert(__traits(isUnsigned, UnsignedEnum));
|
|
static assert(__traits(isUnsigned, uint4));
|
|
|
|
static assert(!__traits(isUnsigned, int));
|
|
static assert(!__traits(isUnsigned, float));
|
|
static assert(!__traits(isUnsigned, SignedEnum));
|
|
static assert(!__traits(isUnsigned, uint[4]));
|
|
static assert(!__traits(isUnsigned, void*));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isStaticArray))
|
|
|
|
$(P Works like $(D isArithmetic), except it's for static array
|
|
types.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.simd : int4;
|
|
|
|
enum E : int[4] { a = [1, 2, 3, 4] }
|
|
|
|
static array = [1, 2, 3]; // Not a static array: the type is inferred as int[] not int[3].
|
|
|
|
static assert(__traits(isStaticArray, void[0]));
|
|
static assert(__traits(isStaticArray, E));
|
|
static assert(!__traits(isStaticArray, int4));
|
|
static assert(!__traits(isStaticArray, array));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isAssociativeArray))
|
|
|
|
$(P Works like $(D isArithmetic), except it's for associative array
|
|
types.)
|
|
|
|
$(H3 $(GNAME isAbstractClass))
|
|
|
|
$(P If the arguments are all either types that are abstract classes,
|
|
or expressions that are typed as abstract classes, then $(D true)
|
|
is returned.
|
|
Otherwise, $(D false) is returned.
|
|
If there are no arguments, $(D false) is returned.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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*));
|
|
}
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
true
|
|
true
|
|
false
|
|
false
|
|
)
|
|
|
|
$(H3 $(GNAME isFinalClass))
|
|
|
|
$(P Works like $(D isAbstractClass), except it's for final
|
|
classes.)
|
|
|
|
$(H3 $(GNAME isCopyable))
|
|
|
|
$(P Takes one argument. If that argument is a copyable type then $(D true) is returned,
|
|
otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
struct S
|
|
{
|
|
}
|
|
static assert( __traits(isCopyable, S));
|
|
|
|
struct T
|
|
{
|
|
@disable this(this); // disable copy construction
|
|
}
|
|
static assert(!__traits(isCopyable, T));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isPOD))
|
|
|
|
$(P Takes one argument, which must be a type. It returns
|
|
$(D true) if the type is a $(DDSUBLINK glossary, pod, POD) type, otherwise $(D false).)
|
|
|
|
$(H3 $(GNAME toType))
|
|
|
|
$(P Takes a single argument, which must evaluate to an expression of type `string`.
|
|
The contents of the string must correspond to the $(DDSUBLINK spec/abi, name_mangling, mangled contents of a type)
|
|
that has been seen by the implementation.)
|
|
|
|
$(P Only D mangling is supported. Other manglings, such as C++ mangling, are not.)
|
|
|
|
$(P The value returned is a type.)
|
|
|
|
---
|
|
template Type(T) { alias Type = T; }
|
|
|
|
Type!(__traits(toType, "i")) j = 3; // j is declared as type `int`
|
|
|
|
static assert(is(Type!(__traits(toType, (int*).mangleof)) == int*));
|
|
|
|
__traits(toType, "i") x = 4; // x is also declared as type `int`
|
|
---
|
|
|
|
$(RATIONALE Provides the inverse operation of the $(DDSUBLINK spec/property, mangleof, `.mangleof`) property.)
|
|
|
|
$(H3 $(GNAME isZeroInit))
|
|
|
|
$(P Takes one argument which must be a type. If the type's
|
|
$(DDSUBLINK spec/property, init, default initializer) is all zero
|
|
bits then `true` is returned, otherwise `false`.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
struct S1 { int x; }
|
|
struct S2 { int x = -1; }
|
|
|
|
static assert(__traits(isZeroInit, S1));
|
|
static assert(!__traits(isZeroInit, S2));
|
|
|
|
void test()
|
|
{
|
|
int x = 3;
|
|
static assert(__traits(isZeroInit, typeof(x)));
|
|
}
|
|
|
|
// `isZeroInit` will always return true for a class C
|
|
// because `C.init` is null reference.
|
|
|
|
class C { int x = -1; }
|
|
|
|
static assert(__traits(isZeroInit, C));
|
|
|
|
// For initializing arrays of element type `void`.
|
|
static assert(__traits(isZeroInit, void));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME hasCopyConstructor))
|
|
|
|
$(P The argument is a type. If it is a struct with a copy constructor, returns $(D true). Otherwise, return $(D false). Note that a copy constructor is distinct from a postblit.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
|
|
import std.stdio;
|
|
|
|
struct S
|
|
{
|
|
}
|
|
|
|
class C
|
|
{
|
|
}
|
|
|
|
struct P
|
|
{
|
|
this(ref P rhs) {}
|
|
}
|
|
|
|
struct B
|
|
{
|
|
this(this) {}
|
|
}
|
|
|
|
void main()
|
|
{
|
|
writeln(__traits(hasCopyConstructor, S)); // false
|
|
writeln(__traits(hasCopyConstructor, C)); // false
|
|
writeln(__traits(hasCopyConstructor, P)); // true
|
|
writeln(__traits(hasCopyConstructor, B)); // false, this is a postblit
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME hasPostblit))
|
|
|
|
$(P The argument is a type. If it is a struct with a postblit, returns $(D true). Otherwise, return $(D false). Note a postblit is distinct from a copy constructor.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
|
|
import std.stdio;
|
|
|
|
struct S
|
|
{
|
|
}
|
|
|
|
class C
|
|
{
|
|
}
|
|
|
|
struct P
|
|
{
|
|
this(ref P rhs) {}
|
|
}
|
|
|
|
struct B
|
|
{
|
|
this(this) {}
|
|
}
|
|
|
|
|
|
void main()
|
|
{
|
|
writeln(__traits(hasPostblit, S)); // false
|
|
writeln(__traits(hasPostblit, C)); // false
|
|
writeln(__traits(hasPostblit, P)); // false, this is a copy ctor
|
|
writeln(__traits(hasPostblit, B)); // true
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getAliasThis))
|
|
|
|
$(P Takes one argument, a type. If the type has `alias this` declarations,
|
|
returns a *ValueSeq* of the names (as `string`s) of the members used in
|
|
those declarations. Otherwise returns an empty sequence.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
alias AliasSeq(T...) = T;
|
|
|
|
struct S1
|
|
{
|
|
string var;
|
|
alias var this;
|
|
}
|
|
static assert(__traits(getAliasThis, S1) == AliasSeq!("var"));
|
|
static assert(__traits(getAliasThis, int).length == 0);
|
|
|
|
pragma(msg, __traits(getAliasThis, S1));
|
|
pragma(msg, __traits(getAliasThis, int));
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
tuple("var")
|
|
tuple()
|
|
)
|
|
|
|
$(H3 $(GNAME getPointerBitmap))
|
|
|
|
$(P The argument is a type.
|
|
The result is an array of $(D size_t) describing the memory used by an instance of the given type.
|
|
)
|
|
$(P The first element of the array is the size of the type (for classes it is
|
|
the $(GLINK classInstanceSize)).)
|
|
$(P The following elements describe the locations of GC managed pointers within the
|
|
memory occupied by an instance of the type.
|
|
For type T, there are $(D T.sizeof / size_t.sizeof) possible pointers represented
|
|
by the bits of the array values.)
|
|
$(P This array can be used by a precise GC to avoid false pointers.)
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
void main()
|
|
{
|
|
static class C
|
|
{
|
|
// implicit virtual function table pointer not marked
|
|
// implicit monitor field not marked, usually managed manually
|
|
C next;
|
|
size_t sz;
|
|
void* p;
|
|
void function () fn; // not a GC managed pointer
|
|
}
|
|
|
|
static struct S
|
|
{
|
|
size_t val1;
|
|
void* p;
|
|
C c;
|
|
byte[] arr; // { length, ptr }
|
|
void delegate () dg; // { context, func }
|
|
}
|
|
|
|
static assert (__traits(getPointerBitmap, C) == [6*size_t.sizeof, 0b010100]);
|
|
static assert (__traits(getPointerBitmap, S) == [7*size_t.sizeof, 0b0110110]);
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getVirtualFunctions))
|
|
|
|
$(P The same as $(GLINK getVirtualMethods), except that
|
|
final functions that do not override anything are included.
|
|
)
|
|
|
|
$(H3 $(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 symbol sequence of the virtual overloads of that function.
|
|
It does not include final functions that do not override anything.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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 b = typeof(__traits(getVirtualMethods, D, "foo"));
|
|
foreach (t; b)
|
|
writeln(typeid(t));
|
|
|
|
auto i = __traits(getVirtualMethods, d, "foo")[1](1);
|
|
writeln(i);
|
|
}
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
void()
|
|
int()
|
|
void()
|
|
int()
|
|
2
|
|
)
|
|
|
|
$(H3 $(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.
|
|
)
|
|
|
|
$(H3 $(GNAME classInstanceAlignment))
|
|
|
|
$(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 alignment
|
|
of a runtime instance of the class type.
|
|
It is based on the static type of a class, not the
|
|
polymorphic type.
|
|
)
|
|
|
|
$(H3 $(GNAME initSymbol))
|
|
|
|
$(P Takes a single argument, which must evaluate to a `class`, `struct` or `union` type.
|
|
Returns a `const(void)[]` that holds the initial state of any instance of the supplied type.
|
|
The slice is constructed for any type `T` as follows:
|
|
|
|
- `ptr` points to either the initializer symbol of `T`
|
|
or `null` if `T` is a zero-initialized struct / unions.
|
|
|
|
- `length` is equal to the size of an instance, i.e. `T.sizeof` for structs / unions and
|
|
$(RELATIVE_LINK2 classInstanceSize, $(D __traits(classInstanceSize, T)`)) for classes.
|
|
)
|
|
|
|
$(P
|
|
This trait matches the behaviour of `TypeInfo.initializer()` but can also be used when
|
|
`TypeInfo` is not available.
|
|
)
|
|
|
|
$(P
|
|
This traits is not available during $(DDSUBLINK glossary, ctfe, CTFE) because the actual address
|
|
of the initializer symbol will be set by the linker and hence is not available at compile time.
|
|
)
|
|
|
|
---
|
|
class C
|
|
{
|
|
int i = 4;
|
|
}
|
|
|
|
/// Initializes a malloc'ed instance of `C`
|
|
void main()
|
|
{
|
|
const void[] initSym = __traits(initSymbol, C);
|
|
|
|
void* ptr = malloc(initSym.length);
|
|
scope (exit) free(ptr);
|
|
|
|
ptr[0..initSym.length] = initSym[];
|
|
|
|
C c = cast(C) ptr;
|
|
assert(c.i == 4);
|
|
}
|
|
---
|
|
|
|
|
|
$(H2 $(LNAME2 functions, Function Traits))
|
|
|
|
$(H3 $(GNAME isDisabled))
|
|
|
|
$(P Takes one argument and returns `true` if it's a function declaration
|
|
marked with `@disable`.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
struct Foo
|
|
{
|
|
@disable void foo();
|
|
void bar(){}
|
|
}
|
|
|
|
static assert(__traits(isDisabled, Foo.foo));
|
|
static assert(!__traits(isDisabled, Foo.bar));
|
|
---
|
|
)
|
|
|
|
$(P For any other declaration even if `@disable` is a syntactically valid
|
|
attribute `false` is returned because the annotation has no effect.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
@disable struct Bar{}
|
|
|
|
static assert(!__traits(isDisabled, Bar));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getVirtualIndex))
|
|
|
|
$(P Takes a single argument which must evaluate to a function.
|
|
The result is a $(CODE ptrdiff_t) containing the index
|
|
of that function within the vtable of the parent type.
|
|
If the function passed in is final and does not override
|
|
a virtual function, $(D -1) is returned instead.
|
|
)
|
|
|
|
$(H3 $(GNAME isVirtualFunction))
|
|
|
|
$(P The same as $(GLINK isVirtualMethod), except
|
|
that final functions that don't override anything return true.
|
|
)
|
|
|
|
$(H3 $(GNAME isVirtualMethod))
|
|
|
|
$(P Takes one argument. If that argument is a virtual function,
|
|
$(D true) is returned, otherwise $(D false).
|
|
Final functions that don't override anything return false.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isAbstractFunction))
|
|
|
|
$(P Takes one argument. If that argument is an abstract function,
|
|
$(D true) is returned, otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isFinalFunction))
|
|
|
|
$(P Takes one argument. If that argument is a final function,
|
|
$(D true) is returned, otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isOverrideFunction))
|
|
|
|
$(P Takes one argument. If that argument is a function marked with
|
|
$(D_KEYWORD override), $(D true) is returned, otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import std.stdio;
|
|
|
|
class Base
|
|
{
|
|
void foo() { }
|
|
}
|
|
|
|
class Foo : Base
|
|
{
|
|
override void foo() { }
|
|
void bar() { }
|
|
}
|
|
|
|
void main()
|
|
{
|
|
writeln(__traits(isOverrideFunction, Base.foo)); // false
|
|
writeln(__traits(isOverrideFunction, Foo.foo)); // true
|
|
writeln(__traits(isOverrideFunction, Foo.bar)); // false
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isStaticFunction))
|
|
|
|
$(P Takes one argument. If that argument is a static function,
|
|
meaning it has no context pointer,
|
|
$(D true) is returned, otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
struct A
|
|
{
|
|
int foo() { return 3; }
|
|
static int boo(int a) { return a; }
|
|
}
|
|
|
|
void main()
|
|
{
|
|
assert(__traits(isStaticFunction, A.boo));
|
|
assert(!__traits(isStaticFunction, A.foo));
|
|
assert(__traits(isStaticFunction, main));
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isReturnOnStack))
|
|
|
|
$(P
|
|
Takes one argument which must either be a function symbol, function literal,
|
|
a delegate, or a function pointer.
|
|
It returns a `bool` which is `true` if the return value of the function is
|
|
returned on the stack via a pointer to it passed as a hidden extra
|
|
parameter to the function.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
struct S { int[20] a; }
|
|
int test1();
|
|
S test2();
|
|
|
|
static assert(__traits(isReturnOnStack, test1) == false);
|
|
static assert(__traits(isReturnOnStack, test2) == true);
|
|
---
|
|
)
|
|
|
|
$(IMPLEMENTATION_DEFINED
|
|
This is determined by the function ABI calling convention in use,
|
|
which is often complex.
|
|
)
|
|
|
|
$(BEST_PRACTICE This has applications in:
|
|
$(OL
|
|
$(LI Returning values in registers is often faster, so this can be used as
|
|
a check on a hot function to ensure it is using the fastest method.)
|
|
$(LI When using inline assembly to correctly call a function.)
|
|
$(LI Testing that the compiler does this correctly is normally hackish and awkward,
|
|
this enables efficient, direct, and simple testing.)
|
|
))
|
|
|
|
$(SECTION3 $(GNAME getFunctionVariadicStyle),
|
|
$(P
|
|
Takes one argument which must either be a function symbol, or a type
|
|
that is a function, delegate or a function pointer.
|
|
It returns a string identifying the kind of
|
|
$(LINK2 function.html#variadic, variadic arguments) that are supported.
|
|
)
|
|
|
|
$(TABLE2 getFunctionVariadicStyle,
|
|
$(THEAD result, kind, access, example)
|
|
$(TROW $(D "none"), not a variadic function, $(NBSP), $(D void foo();))
|
|
$(TROW $(D "argptr"), D style variadic function, $(D _argptr) and $(D _arguments), $(D void bar(...)))
|
|
$(TROW $(D "stdarg"), C style variadic function, $(LINK2 $(ROOT_DIR)phobos/core_stdc_stdarg.html, $(D core.stdc.stdarg)), $(D extern (C) void abc(int, ...)))
|
|
$(TROW $(D "typesafe"), typesafe variadic function, array on stack, $(D void def(int[] ...)))
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.stdc.stdarg;
|
|
|
|
void novar() {}
|
|
extern(C) void cstyle(int, ...) {}
|
|
extern(C++) void cppstyle(int, ...) {}
|
|
void dstyle(...) {}
|
|
void typesafe(int[]...) {}
|
|
|
|
static assert(__traits(getFunctionVariadicStyle, novar) == "none");
|
|
static assert(__traits(getFunctionVariadicStyle, cstyle) == "stdarg");
|
|
static assert(__traits(getFunctionVariadicStyle, cppstyle) == "stdarg");
|
|
static assert(__traits(getFunctionVariadicStyle, dstyle) == "argptr");
|
|
static assert(__traits(getFunctionVariadicStyle, typesafe) == "typesafe");
|
|
|
|
static assert(__traits(getFunctionVariadicStyle, (int[] a...) {}) == "typesafe");
|
|
static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg");
|
|
---
|
|
)
|
|
)
|
|
|
|
$(SECTION3 $(GNAME getFunctionAttributes),
|
|
$(P
|
|
Takes one argument which must either be a function symbol, function literal,
|
|
or a function pointer. It returns a string *ValueSeq* of all the attributes of
|
|
that function $(B excluding) any user-defined attributes (UDAs can be
|
|
retrieved with the $(GLINK getAttributes) trait).
|
|
If no attributes exist it will return an empty sequence.
|
|
)
|
|
|
|
|
|
$(B Note:) The order of the attributes in the returned sequence is
|
|
implementation-defined and should not be relied upon.
|
|
|
|
$(P
|
|
A list of currently supported attributes are:)
|
|
$(UL $(LI $(D pure), $(D nothrow), $(D @nogc), $(D @property), $(D @system), $(D @trusted), $(D @safe), $(D ref) and $(D @live)))
|
|
$(B Note:) $(D ref) is a function attribute even though it applies to the return type.
|
|
|
|
$(P
|
|
Additionally the following attributes are only valid for non-static member functions:)
|
|
$(UL $(LI $(D const), $(D immutable), $(D inout), $(D shared)))
|
|
|
|
For example:
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
int sum(int x, int y) pure nothrow { return x + y; }
|
|
|
|
pragma(msg, __traits(getFunctionAttributes, sum));
|
|
|
|
struct S
|
|
{
|
|
void test() const @system { }
|
|
}
|
|
|
|
pragma(msg, __traits(getFunctionAttributes, S.test));
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
tuple("pure", "nothrow", "@system")
|
|
tuple("const", "@system")
|
|
)
|
|
|
|
$(P Note that some attributes can be inferred. For example:)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; }));
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
tuple("pure", "nothrow", "@nogc", "@trusted")
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
$(H2 $(LNAME2 function-parameters, Function Parameter Traits))
|
|
|
|
$(H3 $(GNAME isRef), $(GNAME isOut), $(GNAME isLazy))
|
|
|
|
$(P Takes one argument. If that argument is a declaration,
|
|
$(D true) is returned if it is $(D_KEYWORD ref), $(D_KEYWORD out),
|
|
or $(D_KEYWORD lazy), otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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));
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getParameterStorageClasses))
|
|
|
|
$(P
|
|
Takes two arguments.
|
|
The first must either be a function symbol, a function call, or a type
|
|
that is a function, delegate or a function pointer.
|
|
The second is an integer identifying which parameter, where the first parameter is
|
|
0.
|
|
It returns a *ValueSeq* of strings representing the storage classes of that parameter.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
ref int foo(return ref const int* p, scope int* a, out int b, lazy int c);
|
|
|
|
static assert(__traits(getParameterStorageClasses, foo, 0)[0] == "return");
|
|
static assert(__traits(getParameterStorageClasses, foo, 0)[1] == "ref");
|
|
|
|
static assert(__traits(getParameterStorageClasses, foo, 1)[0] == "scope");
|
|
static assert(__traits(getParameterStorageClasses, foo, 2)[0] == "out");
|
|
static assert(__traits(getParameterStorageClasses, typeof(&foo), 3)[0] == "lazy");
|
|
|
|
int* p, a;
|
|
int b, c;
|
|
|
|
static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 1)[0] == "scope");
|
|
static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 2)[0] == "out");
|
|
static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 3)[0] == "lazy");
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME parameters))
|
|
|
|
$(P May only be used inside a function. Takes no arguments, and returns
|
|
a sequence of the enclosing function's parameters.)
|
|
|
|
$(P If the function is nested, the parameters returned are those of the
|
|
inner function, not the outer one.)
|
|
|
|
---
|
|
int add(int x, int y)
|
|
{
|
|
return x + y;
|
|
}
|
|
|
|
int forwardToAdd(int x, int y)
|
|
{
|
|
return add(__traits(parameters));
|
|
// equivalent to;
|
|
//return add(x, y);
|
|
}
|
|
|
|
int nestedExample(int x)
|
|
{
|
|
// outer function's parameters
|
|
static assert(typeof(__traits(parameters)).length == 1);
|
|
|
|
int add(int x, int y)
|
|
{
|
|
// inner function's parameters
|
|
static assert(typeof(__traits(parameters)).length == 2);
|
|
return x + y;
|
|
}
|
|
|
|
return add(x, x);
|
|
}
|
|
|
|
class C
|
|
{
|
|
int opApply(int delegate(size_t, C) dg)
|
|
{
|
|
if (dg(0, this)) return 1;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void foreachExample(C c, int x)
|
|
{
|
|
foreach(idx; 0..5)
|
|
{
|
|
static assert(is(typeof(__traits(parameters)) == AliasSeq!(C, int)));
|
|
}
|
|
foreach(idx, elem; c)
|
|
{
|
|
// __traits(parameters) sees past the delegate passed to opApply
|
|
static assert(is(typeof(__traits(parameters)) == AliasSeq!(C, int)));
|
|
}
|
|
}
|
|
---
|
|
|
|
|
|
$(H2 $(LNAME2 symbols, Symbol Traits))
|
|
|
|
$(H3 $(GNAME isNested))
|
|
|
|
$(P Takes one argument.
|
|
It returns $(D true) if the argument is a nested type which internally
|
|
stores a context pointer, otherwise it returns $(D false).
|
|
Nested types can be $(DDSUBLINK spec/class, nested, classes),
|
|
$(DDSUBLINK spec/struct, nested, structs), and
|
|
$(DDSUBLINK spec/function, variadicnested, functions).)
|
|
|
|
$(H3 $(GNAME isFuture))
|
|
|
|
$(P Takes one argument. It returns `true` if the argument is a symbol
|
|
marked with the `@future` keyword, otherwise `false`. Currently, only
|
|
functions and variable declarations have support for the `@future` keyword.)
|
|
|
|
$(H3 $(GNAME isDeprecated))
|
|
|
|
$(P Takes one argument. It returns `true` if the argument is a symbol
|
|
marked with the `deprecated` keyword, otherwise `false`.)
|
|
|
|
$(H3 $(GNAME isTemplate))
|
|
|
|
$(P Takes one argument. If that argument or any of its overloads is a template
|
|
then $(D true) is returned, otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
void foo(T)(){}
|
|
static assert(__traits(isTemplate,foo));
|
|
static assert(!__traits(isTemplate,foo!int()));
|
|
static assert(!__traits(isTemplate,"string"));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isModule))
|
|
|
|
$(P Takes one argument. If that argument is a symbol that refers to a
|
|
$(DDLINK spec/module, Modules, module) then $(D true) is returned, otherwise $(D false).
|
|
$(DDSUBLINK spec/module, package-module, Package modules) are considered to be
|
|
modules even if they have not been directly imported as modules.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import core.thread;
|
|
import std.algorithm.sorting;
|
|
|
|
// A regular package (no package.d)
|
|
static assert(!__traits(isModule, core));
|
|
// A package module (has a package.d file)
|
|
// Note that we haven't imported std.algorithm directly.
|
|
// (In other words, we don't have an "import std.algorithm;" directive.)
|
|
static assert(__traits(isModule, std.algorithm));
|
|
// A regular module
|
|
static assert(__traits(isModule, std.algorithm.sorting));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME isPackage))
|
|
|
|
$(P Takes one argument. If that argument is a symbol that refers to a
|
|
$(DDSUBLINK spec/module, PackageName, package) then $(D true) is returned,
|
|
otherwise $(D false).
|
|
)
|
|
|
|
---
|
|
import std.algorithm.sorting;
|
|
static assert(__traits(isPackage, std));
|
|
static assert(__traits(isPackage, std.algorithm));
|
|
static assert(!__traits(isPackage, std.algorithm.sorting));
|
|
---
|
|
|
|
$(H3 $(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,
|
|
$(D true) is returned, otherwise $(D false).
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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, S, "write")); // false, but callable like a member via UFCS
|
|
writeln(__traits(hasMember, int, "sizeof")); // true
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME identifier))
|
|
|
|
$(P Takes one argument, a symbol. Returns the identifier
|
|
for that symbol as a string literal.
|
|
)
|
|
$(SPEC_RUNNABLE_EXAMPLE_RUN
|
|
---
|
|
int var = 123;
|
|
pragma(msg, typeof(var)); // int
|
|
pragma(msg, typeof(__traits(identifier, var))); // string
|
|
writeln(var); // 123
|
|
writeln(__traits(identifier, var)); // "var"
|
|
---
|
|
)
|
|
|
|
$(SECTION3 $(GNAME getAttributes),
|
|
$(P
|
|
Takes one argument, a symbol. Returns a sequence of all attached user-defined attributes.
|
|
If no UDAs exist it will return an empty sequence
|
|
)
|
|
|
|
$(P
|
|
For more information, see: $(DDSUBLINK spec/attribute, uda, User-Defined Attributes)
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
@(3) int a;
|
|
@("string", 7) int b;
|
|
|
|
enum Foo;
|
|
@Foo int c;
|
|
|
|
pragma(msg, __traits(getAttributes, a));
|
|
pragma(msg, __traits(getAttributes, b));
|
|
pragma(msg, __traits(getAttributes, c));
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
tuple(3)
|
|
tuple("string", 7)
|
|
tuple((Foo))
|
|
)
|
|
)
|
|
|
|
$(H3 $(GNAME getLinkage))
|
|
|
|
$(P Takes one argument, which is a declaration symbol, or the type of a function, delegate,
|
|
pointer to function, struct, class, or interface.
|
|
Returns a string representing the $(LINK2 attribute.html#LinkageAttribute, LinkageAttribute)
|
|
of the declaration.
|
|
The string is one of:
|
|
)
|
|
|
|
$(UL
|
|
$(LI $(D "D"))
|
|
$(LI $(D "C"))
|
|
$(LI $(D "C++"))
|
|
$(LI $(D "Windows"))
|
|
$(LI $(D "Objective-C"))
|
|
$(LI $(D "System"))
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
extern (C) int fooc();
|
|
alias aliasc = fooc;
|
|
|
|
static assert(__traits(getLinkage, fooc) == "C");
|
|
static assert(__traits(getLinkage, aliasc) == "C");
|
|
|
|
extern (C++) struct FooCPPStruct {}
|
|
extern (C++) class FooCPPClass {}
|
|
extern (C++) interface FooCPPInterface {}
|
|
|
|
static assert(__traits(getLinkage, FooCPPStruct) == "C++");
|
|
static assert(__traits(getLinkage, FooCPPClass) == "C++");
|
|
static assert(__traits(getLinkage, FooCPPInterface) == "C++");
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getLocation))
|
|
$(P Takes one argument which is a symbol.
|
|
To disambiguate between overloads, pass the result of $(GLINK getOverloads) with the desired index, to `getLocation`.
|
|
Returns a *ValueSeq* of a string and two `int`s which correspond to the filename, line number and column number where the argument
|
|
was declared.
|
|
)
|
|
|
|
$(H3 $(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.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getOverloads))
|
|
|
|
$(P The first argument is an aggregate (e.g. struct/class/module).
|
|
The second argument is a `string` that matches the name of
|
|
the member(s) to return.
|
|
The third argument is a `bool`, and is optional. If `true`, the
|
|
result will also include template overloads.
|
|
The result is a symbol sequence of all the overloads of the supplied name.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import std.stdio;
|
|
|
|
class D
|
|
{
|
|
this() { }
|
|
~this() { }
|
|
void foo() { }
|
|
int foo(int) { return 2; }
|
|
void bar(T)() { return T.init; }
|
|
class bar(int n) {}
|
|
}
|
|
|
|
void main()
|
|
{
|
|
D d = new D();
|
|
|
|
foreach (t; __traits(getOverloads, D, "foo"))
|
|
writeln(typeid(typeof(t)));
|
|
|
|
alias b = typeof(__traits(getOverloads, D, "foo"));
|
|
foreach (t; b)
|
|
writeln(typeid(t));
|
|
|
|
auto i = __traits(getOverloads, d, "foo")[1](1);
|
|
writeln(i);
|
|
|
|
foreach (t; __traits(getOverloads, D, "bar", true))
|
|
writeln(t.stringof);
|
|
}
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
void()
|
|
int()
|
|
void()
|
|
int()
|
|
2
|
|
bar(T)()
|
|
bar(int n)
|
|
)
|
|
|
|
$(H3 $(GNAME getCppNamespaces))
|
|
$(P The argument is a symbol.
|
|
The result is a *ValueSeq* of strings, possibly empty, that correspond to the namespaces the symbol resides in.
|
|
)
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
extern(C++, "ns")
|
|
struct Foo {}
|
|
struct Bar {}
|
|
extern(C++, __traits(getCppNamespaces, Foo)) struct Baz {}
|
|
static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz));
|
|
void main()
|
|
{
|
|
static assert(__traits(getCppNamespaces, Foo)[0] == "ns");
|
|
static assert(!__traits(getCppNamespaces, Bar).length);
|
|
static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz));
|
|
}
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME getVisibility))
|
|
|
|
$(P The argument is a symbol.
|
|
The result is a string giving its visibility level: "public", "private", "protected", "export", or "package".
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import std.stdio;
|
|
|
|
class D
|
|
{
|
|
export void foo() { }
|
|
public int bar;
|
|
}
|
|
|
|
void main()
|
|
{
|
|
D d = new D();
|
|
|
|
auto i = __traits(getVisibility, d.foo);
|
|
writeln(i);
|
|
|
|
auto j = __traits(getVisibility, d.bar);
|
|
writeln(j);
|
|
}
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
export
|
|
public
|
|
)
|
|
|
|
$(H3 $(GNAME getProtection))
|
|
|
|
$(P A backward-compatible alias for $(GLINK getVisibility).)
|
|
|
|
$(H3 $(GNAME getTargetInfo))
|
|
|
|
$(P Receives a string key as argument.
|
|
The result is an expression describing the requested target information.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
version (CppRuntime_Microsoft)
|
|
static assert(__traits(getTargetInfo, "cppRuntimeLibrary") == "libcmt");
|
|
---
|
|
)
|
|
|
|
$(P Keys are implementation defined, allowing relevant data for exotic targets.
|
|
A reliable subset exists which are always available:
|
|
)
|
|
|
|
$(UL
|
|
$(LI $(D "cppRuntimeLibrary") - The C++ runtime library affinity for this toolchain)
|
|
$(LI $(D "cppStd") - The version of the C++ standard supported by $(D extern$(LPAREN)C++$(RPAREN)) code, equivalent to the `__cplusplus` macro in a C++ compiler)
|
|
$(LI $(D "floatAbi") - Floating point ABI; may be $(D "hard"), $(D "soft"), or $(D "softfp"))
|
|
$(LI $(D "objectFormat") - Target object format)
|
|
)
|
|
|
|
$(H3 $(GNAME getUnitTests))
|
|
|
|
$(P
|
|
Takes one argument, a symbol of an aggregate (e.g. struct/class/module).
|
|
The result is a symbol sequence of all the unit test functions of that aggregate.
|
|
The functions returned are like normal nested static functions,
|
|
$(DDSUBLINK glossary, ctfe, CTFE) will work and
|
|
$(DDSUBLINK spec/attribute, uda, UDAs) will be accessible.
|
|
)
|
|
|
|
$(H4 Note:)
|
|
|
|
$(P
|
|
The -unittest flag needs to be passed to the compiler. If the flag
|
|
is not passed $(CODE __traits(getUnitTests)) will always return an
|
|
empty sequence.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
module foo;
|
|
|
|
import core.runtime;
|
|
import std.stdio;
|
|
|
|
struct name { string name; }
|
|
|
|
class Foo
|
|
{
|
|
unittest
|
|
{
|
|
writeln("foo.Foo.unittest");
|
|
}
|
|
}
|
|
|
|
@name("foo") unittest
|
|
{
|
|
writeln("foo.unittest");
|
|
}
|
|
|
|
template Tuple (T...)
|
|
{
|
|
alias Tuple = T;
|
|
}
|
|
|
|
shared static this()
|
|
{
|
|
// Override the default unit test runner to do nothing. After that, "main" will
|
|
// be called.
|
|
Runtime.moduleUnitTester = { return true; };
|
|
}
|
|
|
|
void main()
|
|
{
|
|
writeln("start main");
|
|
|
|
alias tests = Tuple!(__traits(getUnitTests, foo));
|
|
static assert(tests.length == 1);
|
|
|
|
alias attributes = Tuple!(__traits(getAttributes, tests[0]));
|
|
static assert(attributes.length == 1);
|
|
|
|
foreach (test; tests)
|
|
test();
|
|
|
|
foreach (test; __traits(getUnitTests, Foo))
|
|
test();
|
|
}
|
|
---
|
|
)
|
|
|
|
$(P By default, the above will print:)
|
|
|
|
$(CONSOLE
|
|
start main
|
|
foo.unittest
|
|
foo.Foo.unittest
|
|
)
|
|
|
|
$(H3 $(GNAME parent))
|
|
|
|
$(P Takes a single argument which must evaluate to a symbol.
|
|
The result is the symbol that is the parent of it.
|
|
)
|
|
|
|
$(H3 $(GNAME child))
|
|
|
|
$(P Takes two arguments.
|
|
The first must be a symbol or expression.
|
|
The second is a symbol, such as an alias to a member of the first
|
|
argument.
|
|
The result is the second argument interpreted with its $(D this)
|
|
context set to the value of the first argument.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import std.stdio;
|
|
|
|
struct A
|
|
{
|
|
int i;
|
|
int foo(int j) {
|
|
return i * j;
|
|
}
|
|
T bar(T)(T t) {
|
|
return i + t;
|
|
}
|
|
}
|
|
|
|
alias Ai = A.i;
|
|
alias Abar = A.bar!int;
|
|
|
|
void main()
|
|
{
|
|
A a;
|
|
|
|
__traits(child, a, Ai) = 3;
|
|
writeln(a.i);
|
|
writeln(__traits(child, a, A.foo)(2));
|
|
writeln(__traits(child, a, Abar)(5));
|
|
}
|
|
---
|
|
)
|
|
|
|
Prints:
|
|
|
|
$(CONSOLE
|
|
3
|
|
6
|
|
8
|
|
)
|
|
|
|
$(H3 $(GNAME allMembers))
|
|
|
|
$(P Takes a single argument, which must evaluate to either
|
|
a module, a struct, a union, a class, an interface, an enum, or a
|
|
template instantiation.
|
|
|
|
A sequence of string literals is returned, each of which
|
|
is the name of a member of that argument combined with all
|
|
of the members of its base classes (if the argument is a class).
|
|
No name is repeated.
|
|
Builtin properties are not included.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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.)
|
|
|
|
$(H3 $(GNAME derivedMembers))
|
|
|
|
$(P Takes a single argument, which must evaluate to either
|
|
a type or an expression of type.
|
|
A sequence 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.
|
|
)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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.)
|
|
|
|
$(H3 $(GNAME isSame))
|
|
|
|
$(P Compares two arguments and evaluates to `bool`.)
|
|
|
|
$(P The result is `true` if the two arguments are the same symbol
|
|
(once aliases are resolved).)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
struct S { }
|
|
|
|
int foo();
|
|
int bar();
|
|
|
|
static assert(__traits(isSame, foo, foo));
|
|
static assert(!__traits(isSame, foo, bar));
|
|
static assert(!__traits(isSame, foo, S));
|
|
static assert(__traits(isSame, S, S));
|
|
static assert(!__traits(isSame, object, S));
|
|
static assert(__traits(isSame, object, object));
|
|
|
|
alias daz = foo;
|
|
static assert(__traits(isSame, foo, daz));
|
|
---
|
|
)
|
|
|
|
$(P The result is `true` if the two arguments are expressions
|
|
made up of literals or enums that evaluate to the same value.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
enum e = 3;
|
|
static assert(__traits(isSame, (e), 3));
|
|
static assert(__traits(isSame, 5, 2 + e));
|
|
---
|
|
)
|
|
$(P If the two arguments are both
|
|
$(DDSUBLINK spec/expression, function_literals, lambda functions) (or aliases
|
|
to lambda functions), then they are compared for equality. For
|
|
the comparison to be computed correctly, the following conditions
|
|
must be met for both lambda functions:)
|
|
|
|
$(OL
|
|
$(LI The lambda function arguments must not have a template
|
|
instantiation as an explicit argument type. Any other argument
|
|
types (basic, user-defined, template) are supported.)
|
|
$(LI The lambda function body must contain a single expression
|
|
(no return statement) which contains only numeric values,
|
|
manifest constants, enum values, function arguments and function
|
|
calls. If the expression contains local variables or return
|
|
statements, the function is considered incomparable.)
|
|
)
|
|
|
|
$(P If these constraints aren't fulfilled, the function is considered
|
|
incomparable and the result is $(D false).)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
static assert(__traits(isSame, (a, b) => a + b, (c, d) => c + d));
|
|
static assert(__traits(isSame, a => ++a, b => ++b));
|
|
static assert(!__traits(isSame, (int a, int b) => a + b, (a, b) => a + b));
|
|
static assert(__traits(isSame, (a, b) => a + b + 10, (c, d) => c + d + 10));
|
|
---
|
|
)
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
int f() { return 2; }
|
|
|
|
void test(alias pred)()
|
|
{
|
|
// f() from main is a different function from top-level f()
|
|
static assert(!__traits(isSame, (int a) => a + f(), pred));
|
|
}
|
|
|
|
void main()
|
|
{
|
|
// lambdas accessing local variables are considered incomparable
|
|
int b;
|
|
static assert(!__traits(isSame, a => a + b, a => a + b));
|
|
|
|
// lambdas calling other functions are comparable
|
|
int f() { return 3;}
|
|
static assert(__traits(isSame, a => a + f(), a => a + f()));
|
|
test!((int a) => a + f())();
|
|
}
|
|
---
|
|
)
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
class A
|
|
{
|
|
int a;
|
|
this(int a)
|
|
{
|
|
this.a = a;
|
|
}
|
|
}
|
|
|
|
class B
|
|
{
|
|
int a;
|
|
this(int a)
|
|
{
|
|
this.a = a;
|
|
}
|
|
}
|
|
|
|
static assert(__traits(isSame, (A a) => ++a.a, (A b) => ++b.a));
|
|
// lambdas with different data types are considered incomparable,
|
|
// even if the memory layout is the same
|
|
static assert(!__traits(isSame, (A a) => ++a.a, (B a) => ++a.a));
|
|
---
|
|
)
|
|
|
|
$(P If the two arguments are tuples then the result is `true` if the
|
|
two tuples, after expansion, have the same length and if each pair
|
|
of nth argument respects the constraints previously specified.)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
import std.meta;
|
|
|
|
struct S { }
|
|
|
|
// like __traits(isSame,0,0) && __traits(isSame,1,1)
|
|
static assert(__traits(isSame, AliasSeq!(0,1), AliasSeq!(0,1)));
|
|
// like __traits(isSame,S,std.meta) && __traits(isSame,1,1)
|
|
static assert(!__traits(isSame, AliasSeq!(S,1), AliasSeq!(std.meta,1)));
|
|
// the length of the sequences is different
|
|
static assert(!__traits(isSame, AliasSeq!(1), AliasSeq!(1,2)));
|
|
---
|
|
)
|
|
|
|
$(H3 $(GNAME compiles))
|
|
|
|
$(P Returns a bool $(D 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 $(D false).)
|
|
|
|
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
|
|
---
|
|
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.)
|
|
)
|
|
|
|
$(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling)
|
|
|
|
Macros:
|
|
CHAPTER=25
|
|
TITLE=Traits
|