Update traits completion

This commit is contained in:
WebFreak001 2025-12-26 22:11:20 +01:00 committed by Jan Jurzitza
parent 5c3e15b58a
commit e6e6e8e174
4 changed files with 618 additions and 176 deletions

View File

@ -23,7 +23,8 @@ immutable ConstantCompletion[] traits = [
ConstantCompletion("allMembers", `$(P Takes a single argument, which must evaluate to either ConstantCompletion("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 a module, a struct, a union, a class, an interface, an enum, or a
template instantiation. template instantiation.
)
$(P
A sequence of string literals is returned, each of which A sequence of string literals is returned, each of which
is the name of a member of that argument combined with all 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). of the members of its base classes (if the argument is a class).
@ -120,14 +121,27 @@ polymorphic type.
compile (are semantically correct). compile (are semantically correct).
The arguments can be symbols, types, or expressions that The arguments can be symbols, types, or expressions that
are syntactically correct. are syntactically correct.
The arguments cannot be statements or declarations. The arguments cannot be statements or declarations - instead
these can be wrapped in a $(DDSUBLINK spec/expression, function_literals,
function literal) expression.
) )
$(P If there are no arguments, the result is $(D false).) $(P If there are no arguments, the result is $(D false).)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
import std.stdio; static assert(!__traits(compiles));
static assert(__traits(compiles, 1 + 1)); // expression
static assert(__traits(compiles, typeof(1))); // type
static assert(__traits(compiles, object)); // symbol
static assert(__traits(compiles, 1, 2, 3, int, long));
static assert(!__traits(compiles, 3[1])); // semantic error
static assert(!__traits(compiles, 1, 2, 3, int, long, 3[1]));
enum n = 3;
// wrap a declaration/statement in a function literal
static assert(__traits(compiles, { int[n] arr; }));
static assert(!__traits(compiles, { foreach (e; n) {} }));
struct S struct S
{ {
@ -135,29 +149,23 @@ struct S
int s2; int s2;
} }
int foo(); static assert(__traits(compiles, S.s1 = 0));
int bar(); static assert(!__traits(compiles, S.s2 = 0));
static assert(!__traits(compiles, S.s3));
void main() int foo();
{
writeln(__traits(compiles)); // false static assert(__traits(compiles, foo));
writeln(__traits(compiles, foo)); // true static assert(__traits(compiles, foo + 1)); // call foo with optional parens
writeln(__traits(compiles, foo + 1)); // true static assert(!__traits(compiles, &foo + 1));
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:) $(P This is useful for:)
$(UL $(UL
$(LI Giving better error messages inside generic code than $(LI Giving better error messages (using $(DDSUBLINK spec/version, static-assert,
` ~ "`" ~ `static assert` ~ "`" ~ `)) inside generic code than
the sometimes hard to follow compiler ones.) the sometimes hard to follow compiler ones.)
$(LI Doing a finer grained specialization than template $(LI Doing a finer grained specialization than template
partial specialization allows for.) partial specialization allows for.)
@ -193,6 +201,53 @@ void main()
$(P The order in which the strings appear in the result $(P The order in which the strings appear in the result
is not defined.)`), is not defined.)`),
ConstantCompletion("fullyQualifiedName", `$(P Gets the fully qualified name of a type or symbol.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
-----------------
module myModule;
int i;
static assert(__traits(fullyQualifiedName, i) == "myModule.i");
struct MyStruct {}
static assert(__traits(fullyQualifiedName, const MyStruct[]) == "const(myModule.MyStruct[])");
-----------------
)`),
ConstantCompletion("fullyQualifiedName", `$(P Takes one argument, which can be a type, expression, or symbol, and returns a string.)
$(UL
$(LI A $(D type) returns a string representing the type.)
$(LI A $(D expression) returns a string representing the type of the expression.)
$(LI A $(D symbol) returns a string representing the fully qualified name of the symbol.)
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
module plugh;
import std.stdio;
void main()
{
auto s = __traits(fullyQualifiedName, int);
writeln(s);
auto t = __traits(fullyQualifiedName, 1.0);
writeln(t);
auto u = __traits(fullyQualifiedName, t);
writeln(u);
}
---
)
Prints:
$(CONSOLE
int
double
plugh.main.t
)`),
ConstantCompletion("getAliasThis", `$(P Takes one argument, a type. If the type has ` ~ "`" ~ `alias this` ~ "`" ~ ` declarations, ConstantCompletion("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 returns a *ValueSeq* of the names (as ` ~ "`" ~ `string` ~ "`" ~ `s) of the members used in
those declarations. Otherwise returns an empty sequence. those declarations. Otherwise returns an empty sequence.
@ -251,6 +306,49 @@ tuple(3)
tuple("string", 7) tuple("string", 7)
tuple((Foo)) tuple((Foo))
) )
)`),
ConstantCompletion("getBitfieldOffset", `$(P Takes one argument, a qualified name that resolve to a field in a struct or class.
)
$(P If the field is a bitfield, it returns as a ` ~ "`" ~ `uint` ~ "`" ~ ` the bit number of the least significant
bit in the field. The rightmost bit is at offset 0, the leftmost bit is at offset 31 (for
32 bit int fields).
)
$(P If the field is a not bitfield, it returns as a ` ~ "`" ~ `uint` ~ "`" ~ ` the number 0.
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct S
{
int a,b;
int :2, c:3;
}
static assert(__traits(getBitfieldOffset, S.b) == 0);
static assert(__traits(getBitfieldOffset, S.c) == 2);
---
)
)`),
ConstantCompletion("getBitfieldWidth", `$(P Takes one argument, a qualified name that resolve to a field in a struct or class.
)
$(P If the field is a bitfield, it returns as a ` ~ "`" ~ `uint` ~ "`" ~ ` the width of the bit field as
a number of bits.
)
$(P If the field is a not bitfield, it returns the number of bits in the type.
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct S
{
int a,b;
int :2, c:3;
}
static assert(__traits(getBitfieldWidth, S.b) == 32);
static assert(__traits(getBitfieldWidth, S.c) == 3);
---
)
)`), )`),
ConstantCompletion("getCppNamespaces", `$(P The argument is a symbol. ConstantCompletion("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. The result is a *ValueSeq* of strings, possibly empty, that correspond to the namespaces the symbol resides in.
@ -432,13 +530,13 @@ void main()
} }
--- ---
)`), )`),
ConstantCompletion("getOverloads", `$(P The first argument is an aggregate (e.g. struct/class/module). ConstantCompletion("getOverloads", `* The first argument is an aggregate type or instance, or a module.
The second argument is a ` ~ "`" ~ `string` ~ "`" ~ ` that matches the name of * The second argument is a ` ~ "`" ~ `string` ~ "`" ~ ` that matches the name of
the member(s) to return. the member(s) to return.
The third argument is a ` ~ "`" ~ `bool` ~ "`" ~ `, and is optional. If ` ~ "`" ~ `true` ~ "`" ~ `, the * The third argument is a ` ~ "`" ~ `bool` ~ "`" ~ `, and is optional. If ` ~ "`" ~ `true` ~ "`" ~ `, the
result will also include template overloads. result will also include template overloads.
The result is a symbol sequence of all the overloads of the supplied name. * The result is a $(DDSUBLINK spec/template, homogeneous_sequences, symbol sequence)
) of all the overloads of the supplied name.
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
@ -446,8 +544,6 @@ import std.stdio;
class D class D
{ {
this() { }
~this() { }
void foo() { } void foo() { }
int foo(int) { return 2; } int foo(int) { return 2; }
void bar(T)() { return T.init; } void bar(T)() { return T.init; }
@ -458,18 +554,24 @@ void main()
{ {
D d = new D(); D d = new D();
foreach (t; __traits(getOverloads, D, "foo")) alias fooOverloads = __traits(getOverloads, D, "foo");
writeln(typeid(typeof(t))); foreach (o; fooOverloads)
writeln(typeid(typeof(o)));
alias b = typeof(__traits(getOverloads, D, "foo")); // typeof on a symbol sequence gives a type sequence
foreach (t; b) foreach (T; typeof(fooOverloads))
writeln(typeid(t)); writeln(typeid(T));
auto i = __traits(getOverloads, d, "foo")[1](1); // calls d.foo(3)
writeln(i); auto i = __traits(getOverloads, d, "foo")[1](3);
assert(i == 2);
foreach (t; __traits(getOverloads, D, "bar", true)) // pass true to include templates
writeln(t.stringof); // calls std.stdio.writeln(i)
__traits(getOverloads, std.stdio, "writeln", true)[0](i);
foreach (o; __traits(getOverloads, D, "bar", true))
writeln(o.stringof);
} }
--- ---
) )
@ -477,10 +579,10 @@ void main()
Prints: Prints:
$(CONSOLE $(CONSOLE
void() void function()
int() int function(int)
void() void function()
int() int function(int)
2 2
bar(T)() bar(T)()
bar(int n) bar(int n)
@ -577,15 +679,13 @@ $(LI $(D "objectFormat") - Target object format)
Takes one argument, a symbol of an aggregate (e.g. struct/class/module). 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 result is a symbol sequence of all the unit test functions of that aggregate.
The functions returned are like normal nested static functions, The functions returned are like normal nested static functions,
$(DDSUBLINK glossary, ctfe, CTFE) will work and $(DDSUBLINK spec/glossary, ctfe, CTFE) will work and
$(DDSUBLINK spec/attribute, uda, UDAs) will be accessible. $(DDSUBLINK spec/attribute, uda, UDAs) will be accessible.
) )
$(H4 Note:) $(NOTE
The ` ~ "`" ~ `-unittest` ~ "`" ~ ` flag needs to be passed to the compiler. If the flag
$(P is not passed, $(CODE __traits(getUnitTests)) will always return an
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. empty sequence.
) )
@ -737,7 +837,9 @@ $(CONSOLE
export export
public public
)`), )`),
ConstantCompletion("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. ConstantCompletion("hasCopyConstructor", `$(P The argument is a type.
If it is a struct with a copy constructor, returns $(D true). Otherwise, return $(D false).
A copy constructor is distinct from a move constructor or a postblit.
) )
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
@ -745,22 +847,18 @@ $(SPEC_RUNNABLE_EXAMPLE_COMPILE
import std.stdio; import std.stdio;
struct S struct S { }
{
}
class C class C { }
{
}
struct P struct P
{ {
this(ref P rhs) {} this(ref P rhs) {} // copy constructor
} }
struct B struct B
{ {
this(this) {} this(this) {} // postblit
} }
void main() void main()
@ -792,11 +890,48 @@ void main()
{ {
S s; S s;
writeln(__traits(hasMember, S, "m")); // true static assert(__traits(hasMember, S, "m"));
writeln(__traits(hasMember, s, "m")); // true static assert(__traits(hasMember, s, "m"));
writeln(__traits(hasMember, S, "y")); // false static assert(!__traits(hasMember, S, "y"));
writeln(__traits(hasMember, S, "write")); // false, but callable like a member via UFCS static assert(!__traits(hasMember, S, "write")); // false, but callable like a member via UFCS
writeln(__traits(hasMember, int, "sizeof")); // true static assert(__traits(hasMember, int, "sizeof"));
static assert(__traits(hasMember, 5, "sizeof"));
}
---
)`),
ConstantCompletion("hasMoveConstructor", `$(P The argument is a type.
If it is a struct with a move constructor, returns $(D true). Otherwise, return $(D false).
A move constructor is distinct from a copy constructor or a postblit.
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
import std.stdio;
struct S
{
this(S rhs) {} // move constructor
}
class C { }
struct P
{
this(ref P rhs) {} // copy constructor
}
struct B
{
this(this) {} // postblit
}
void main()
{
writeln(__traits(hasMoveConstructor, S)); // true
writeln(__traits(hasMoveConstructor, C)); // false
writeln(__traits(hasMoveConstructor, P)); // false
writeln(__traits(hasMoveConstructor, B)); // false, this is a postblit
} }
--- ---
)`), )`),
@ -839,25 +974,22 @@ void main()
ConstantCompletion("identifier", `$(P Takes one argument, a symbol. Returns the identifier ConstantCompletion("identifier", `$(P Takes one argument, a symbol. Returns the identifier
for that symbol as a string literal. for that symbol as a string literal.
) )
$(SPEC_RUNNABLE_EXAMPLE_RUN $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
int var = 123; int var = 123;
pragma(msg, typeof(var)); // int static assert(__traits(identifier, var) == "var");
pragma(msg, typeof(__traits(identifier, var))); // string
writeln(var); // 123
writeln(__traits(identifier, var)); // "var"
--- ---
)`), )`),
ConstantCompletion("initSymbol", `$(P Takes a single argument, which must evaluate to a ` ~ "`" ~ `class` ~ "`" ~ `, ` ~ "`" ~ `struct` ~ "`" ~ ` or ` ~ "`" ~ `union` ~ "`" ~ ` type. ConstantCompletion("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. 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: The slice is constructed for any type ` ~ "`" ~ `T` ~ "`" ~ ` as follows:
)
- ` ~ "`" ~ `ptr` ~ "`" ~ ` points to either the initializer symbol of ` ~ "`" ~ `T` ~ "`" ~ ` - ` ~ "`" ~ `ptr` ~ "`" ~ ` points to either the initializer symbol of ` ~ "`" ~ `T` ~ "`" ~ `
or ` ~ "`" ~ `null` ~ "`" ~ ` if ` ~ "`" ~ `T` ~ "`" ~ ` is a zero-initialized struct / unions. or ` ~ "`" ~ `null` ~ "`" ~ ` if ` ~ "`" ~ `T` ~ "`" ~ ` is a $(RELATIVE_LINK2 isZeroInit, zero-initialized) struct/union.
- ` ~ "`" ~ `length` ~ "`" ~ ` is equal to the size of an instance, i.e. ` ~ "`" ~ `T.sizeof` ~ "`" ~ ` for structs / unions and - ` ~ "`" ~ `length` ~ "`" ~ ` is equal to the size of an instance, i.e. ` ~ "`" ~ `T.sizeof` ~ "`" ~ ` for a struct/union and
$(RELATIVE_LINK2 classInstanceSize, $(D __traits(classInstanceSize, T)` ~ "`" ~ `)) for classes. $(RELATIVE_LINK2 classInstanceSize, $(D __traits(classInstanceSize, T))) for a class.
)
$(P $(P
This trait matches the behaviour of ` ~ "`" ~ `TypeInfo.initializer()` ~ "`" ~ ` but can also be used when This trait matches the behaviour of ` ~ "`" ~ `TypeInfo.initializer()` ~ "`" ~ ` but can also be used when
@ -865,11 +997,14 @@ $(P
) )
$(P $(P
This traits is not available during $(DDSUBLINK glossary, ctfe, CTFE) because the actual address This trait is not available during $(DDSUBLINK spec/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. of the initializer symbol will be set by the linker and hence is not available at compile time.
) )
$(SPEC_RUNNABLE_EXAMPLE_RUN
--- ---
import core.stdc.stdlib;
class C class C
{ {
int i = 4; int i = 4;
@ -883,12 +1018,14 @@ void main()
void* ptr = malloc(initSym.length); void* ptr = malloc(initSym.length);
scope (exit) free(ptr); scope (exit) free(ptr);
ptr[0..initSym.length] = initSym[]; // Note: allocated memory will only be written to through ` ~ "`" ~ `c` ~ "`" ~ `, so cast is safe
ptr[0..initSym.length] = cast(void[]) initSym[];
C c = cast(C) ptr; C c = cast(C) ptr;
assert(c.i == 4); assert(c.i == 4);
} }
---`), ---
)`),
ConstantCompletion("isAbstractClass", `$(P If the arguments are all either types that are abstract classes, ConstantCompletion("isAbstractClass", `$(P If the arguments are all either types that are abstract classes,
or expressions that are typed as abstract classes, then $(D true) or expressions that are typed as abstract classes, then $(D true)
is returned. is returned.
@ -984,6 +1121,10 @@ false
)`), )`),
ConstantCompletion("isAssociativeArray", `$(P Works like $(D isArithmetic), except it's for associative array ConstantCompletion("isAssociativeArray", `$(P Works like $(D isArithmetic), except it's for associative array
types.)`), types.)`),
ConstantCompletion("isCOMClass", `$(P Takes one argument. If that argument is a symbol that refers to a
$(DDSUBLINK spec/class, ClassDeclaration, class declaration) and is a COM class then $(D true) is retuned,
otherwise $(D false).
)`),
ConstantCompletion("isCopyable", `$(P Takes one argument. If that argument is a copyable type then $(D true) is returned, ConstantCompletion("isCopyable", `$(P Takes one argument. If that argument is a copyable type then $(D true) is returned,
otherwise $(D false). otherwise $(D false).
) )
@ -1003,7 +1144,26 @@ static assert(!__traits(isCopyable, T));
--- ---
)`), )`),
ConstantCompletion("isDeprecated", `$(P Takes one argument. It returns ` ~ "`" ~ `true` ~ "`" ~ ` if the argument is a symbol ConstantCompletion("isDeprecated", `$(P Takes one argument. It returns ` ~ "`" ~ `true` ~ "`" ~ ` if the argument is a symbol
marked with the ` ~ "`" ~ `deprecated` ~ "`" ~ ` keyword, otherwise ` ~ "`" ~ `false` ~ "`" ~ `.)`), marked with the ` ~ "`" ~ `deprecated` ~ "`" ~ ` keyword, otherwise ` ~ "`" ~ `false` ~ "`" ~ `.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
deprecated("No longer supported")
int i;
struct A
{
int foo() { return 1; }
deprecated("please use foo")
int bar() { return 1; }
}
static assert(__traits(isDeprecated, i));
static assert(!__traits(isDeprecated, A.foo));
static assert(__traits(isDeprecated, A.bar));
---
)`),
ConstantCompletion("isDisabled", `$(P Takes one argument and returns ` ~ "`" ~ `true` ~ "`" ~ ` if it's a function declaration ConstantCompletion("isDisabled", `$(P Takes one argument and returns ` ~ "`" ~ `true` ~ "`" ~ ` if it's a function declaration
marked with ` ~ "`" ~ `@disable` ~ "`" ~ `.) marked with ` ~ "`" ~ `@disable` ~ "`" ~ `.)
@ -1020,8 +1180,8 @@ static assert(!__traits(isDisabled, Foo.bar));
--- ---
) )
$(P For any other declaration even if ` ~ "`" ~ `@disable` ~ "`" ~ ` is a syntactically valid $(P For any other declaration, even if ` ~ "`" ~ `@disable` ~ "`" ~ ` is a syntactically valid
attribute ` ~ "`" ~ `false` ~ "`" ~ ` is returned because the annotation has no effect.) attribute, ` ~ "`" ~ `false` ~ "`" ~ ` is returned because the annotation has no effect.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
@ -1091,8 +1251,9 @@ static assert(!__traits(isFloating, float[4]));
--- ---
)`), )`),
ConstantCompletion("isFuture", `$(P Takes one argument. It returns ` ~ "`" ~ `true` ~ "`" ~ ` if the argument is a symbol ConstantCompletion("isFuture", `$(P Takes one argument. It returns ` ~ "`" ~ `true` ~ "`" ~ ` if the argument is a symbol
marked with the ` ~ "`" ~ `@future` ~ "`" ~ ` keyword, otherwise ` ~ "`" ~ `false` ~ "`" ~ `. Currently, only marked with the $(DDSUBLINK spec/attribute, future, ` ~ "`" ~ `@__future` ~ "`" ~ ` attribute),
functions and variable declarations have support for the ` ~ "`" ~ `@future` ~ "`" ~ ` keyword.)`), otherwise ` ~ "`" ~ `false` ~ "`" ~ `. Currently, only
functions and variable declarations have support for the ` ~ "`" ~ `@__future` ~ "`" ~ ` keyword.)`),
ConstantCompletion("isIntegral", `$(P If the arguments are all either types that are integral types, ConstantCompletion("isIntegral", `$(P If the arguments are all either types that are integral types,
or expressions that are typed as integral types, then $(D true) or expressions that are typed as integral types, then $(D true)
is returned. is returned.
@ -1234,18 +1395,20 @@ void main()
--- ---
)`), )`),
ConstantCompletion("isPOD", `$(P Takes one argument, which must be a type. It returns ConstantCompletion("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).)`), $(D true) if the type is a $(DDSUBLINK spec/glossary, pod, POD) type, otherwise $(D false).)`),
ConstantCompletion("isPackage", `$(P Takes one argument. If that argument is a symbol that refers to a ConstantCompletion("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, $(DDSUBLINK spec/module, PackageName, package) then $(D true) is returned,
otherwise $(D false). otherwise $(D false).
) )
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
import std.algorithm.sorting; import std.algorithm.sorting;
static assert(__traits(isPackage, std)); static assert(__traits(isPackage, std));
static assert(__traits(isPackage, std.algorithm)); static assert(__traits(isPackage, std.algorithm));
static assert(!__traits(isPackage, std.algorithm.sorting)); static assert(!__traits(isPackage, std.algorithm.sorting));
---`), ---
)`),
ConstantCompletion("isRef", `$(P Takes one argument. If that argument is a declaration, ConstantCompletion("isRef", `$(P Takes one argument. If that argument is a declaration,
$(D true) is returned if it is $(D_KEYWORD ref), $(D_KEYWORD out), $(D true) is returned if it is $(D_KEYWORD ref), $(D_KEYWORD out),
or $(D_KEYWORD lazy), otherwise $(D false). or $(D_KEYWORD lazy), otherwise $(D false).
@ -1330,6 +1493,30 @@ alias daz = foo;
static assert(__traits(isSame, foo, daz)); static assert(__traits(isSame, foo, daz));
--- ---
) )
$(P isSame matches against non-instantiated templates.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct Foo(T){
T x;
}
struct Bar(T){
T x;
}
struct Point(T){
T x;
T y;
}
enum isFooOrBar(alias FB) = __traits(isSame, FB, Foo) || __traits(isSame, FB, Bar);
static assert(isFooOrBar!(Foo));
static assert(isFooOrBar!(Bar));
static assert(!isFooOrBar!(Point));
---
)
$(P The result is ` ~ "`" ~ `true` ~ "`" ~ ` if the two arguments are expressions $(P The result is ` ~ "`" ~ `true` ~ "`" ~ ` if the two arguments are expressions
made up of literals or enums that evaluate to the same value.) made up of literals or enums that evaluate to the same value.)
@ -1515,9 +1702,9 @@ then $(D true) is returned, otherwise $(D false).
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
void foo(T)(){} void foo(T)(){}
static assert(__traits(isTemplate,foo)); static assert(__traits(isTemplate, foo));
static assert(!__traits(isTemplate,foo!int())); static assert(!__traits(isTemplate, foo!int()));
static assert(!__traits(isTemplate,"string")); static assert(!__traits(isTemplate, "string"));
--- ---
)`), )`),
ConstantCompletion("isUnsigned", `$(P If the arguments are all either types that are unsigned types, ConstantCompletion("isUnsigned", `$(P If the arguments are all either types that are unsigned types,
@ -1610,12 +1797,26 @@ static assert(__traits(isZeroInit, void));
--- ---
)`), )`),
ConstantCompletion("parameters", `$(P May only be used inside a function. Takes no arguments, and returns ConstantCompletion("parameters", `$(P May only be used inside a function. Takes no arguments, and returns
a sequence of the enclosing function's parameters.) an $(DDSUBLINK spec/template, lvalue-sequences, lvalue 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.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
alias AliasSeq(A...) = A;
void f(int n, char c)
{
alias PS = __traits(parameters);
PS[0]++; // increment n
static assert(is(typeof(PS) == AliasSeq!(int, char)));
// output parameter names
static foreach (i, p; PS)
{
pragma(msg, __traits(identifier, p));
}
}
int add(int x, int y) int add(int x, int y)
{ {
return x + y; return x + y;
@ -1627,7 +1828,13 @@ int forwardToAdd(int x, int y)
// equivalent to; // equivalent to;
//return add(x, y); //return add(x, y);
} }
---
)
$(P If the function is nested, the parameters returned are those of the
inner function, not the outer one.)
---
int nestedExample(int x) int nestedExample(int x)
{ {
// outer function's parameters // outer function's parameters
@ -1642,7 +1849,8 @@ int nestedExample(int x)
return add(x, x); return add(x, x);
} }
---
---
class C class C
{ {
int opApply(int delegate(size_t, C) dg) int opApply(int delegate(size_t, C) dg)

View File

@ -493,5 +493,5 @@ $(SPEC_SUBNAV_PREV_NEXT attribute, Attributes, expression, Expressions)
) )
Macros: Macros:
CHAPTER=9 CHAPTER=10
TITLE=Pragmas TITLE=Pragmas

View File

@ -49,12 +49,17 @@ $(GNAME TraitsKeyword):
$(RELATIVE_LINK2 isZeroInit, $(D isZeroInit)) $(RELATIVE_LINK2 isZeroInit, $(D isZeroInit))
$(RELATIVE_LINK2 isModule, $(D isModule)) $(RELATIVE_LINK2 isModule, $(D isModule))
$(RELATIVE_LINK2 isPackage, $(D isPackage)) $(RELATIVE_LINK2 isPackage, $(D isPackage))
$(RELATIVE_LINK2 isCOMClass, $(D isCOMClass))
$(RELATIVE_LINK2 hasMember, $(D hasMember)) $(RELATIVE_LINK2 hasMember, $(D hasMember))
$(RELATIVE_LINK2 hasCopyConstructor, $(D hasCopyConstructor)) $(RELATIVE_LINK2 hasCopyConstructor, $(D hasCopyConstructor))
$(RELATIVE_LINK2 hasMoveConstructor, $(D hasMoveConstructor))
$(RELATIVE_LINK2 hasPostblit, $(D hasPostblit)) $(RELATIVE_LINK2 hasPostblit, $(D hasPostblit))
$(RELATIVE_LINK2 identifier, $(D identifier)) $(RELATIVE_LINK2 identifier, $(D identifier))
$(RELATIVE_LINK2 fullyQualifiedName, $(D fullyQualifiedName))
$(RELATIVE_LINK2 getAliasThis, $(D getAliasThis)) $(RELATIVE_LINK2 getAliasThis, $(D getAliasThis))
$(RELATIVE_LINK2 getAttributes, $(D getAttributes)) $(RELATIVE_LINK2 getAttributes, $(D getAttributes))
$(RELATIVE_LINK2 getBitfieldOffset, $(D getBitfieldOffset))
$(RELATIVE_LINK2 getBitfieldWidth, $(D getBitfieldWidth))
$(RELATIVE_LINK2 getFunctionAttributes, $(D getFunctionAttributes)) $(RELATIVE_LINK2 getFunctionAttributes, $(D getFunctionAttributes))
$(RELATIVE_LINK2 getFunctionVariadicStyle, $(D getFunctionVariadicStyle)) $(RELATIVE_LINK2 getFunctionVariadicStyle, $(D getFunctionVariadicStyle))
$(RELATIVE_LINK2 getLinkage, $(D getLinkage)) $(RELATIVE_LINK2 getLinkage, $(D getLinkage))
@ -82,6 +87,7 @@ $(GNAME TraitsKeyword):
$(RELATIVE_LINK2 toType, $(D toType)) $(RELATIVE_LINK2 toType, $(D toType))
$(RELATIVE_LINK2 initSymbol, $(D initSymbol)) $(RELATIVE_LINK2 initSymbol, $(D initSymbol))
$(RELATIVE_LINK2 parameters, $(D parameters)) $(RELATIVE_LINK2 parameters, $(D parameters))
$(RELATIVE_LINK2 fullyQualifiedName, $(D fullyQualifiedName))
$(GNAME TraitsArguments): $(GNAME TraitsArguments):
$(GLINK TraitsArgument) $(GLINK TraitsArgument)
@ -346,7 +352,7 @@ static assert(!__traits(isCopyable, T));
$(H3 $(GNAME isPOD)) $(H3 $(GNAME isPOD))
$(P Takes one argument, which must be a type. It returns $(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).) $(D true) if the type is a $(DDSUBLINK spec/glossary, pod, POD) type, otherwise $(D false).)
$(H3 $(GNAME toType)) $(H3 $(GNAME toType))
@ -404,7 +410,45 @@ static assert(__traits(isZeroInit, void));
$(H3 $(GNAME hasCopyConstructor)) $(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. $(P The argument is a type.
If it is a struct with a copy constructor, returns $(D true). Otherwise, return $(D false).
A copy constructor is distinct from a move constructor or a postblit.
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
import std.stdio;
struct S { }
class C { }
struct P
{
this(ref P rhs) {} // copy constructor
}
struct B
{
this(this) {} // postblit
}
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 hasMoveConstructor))
$(P The argument is a type.
If it is a struct with a move constructor, returns $(D true). Otherwise, return $(D false).
A move constructor is distinct from a copy constructor or a postblit.
) )
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
@ -414,28 +458,27 @@ import std.stdio;
struct S struct S
{ {
this(S rhs) {} // move constructor
} }
class C class C { }
{
}
struct P struct P
{ {
this(ref P rhs) {} this(ref P rhs) {} // copy constructor
} }
struct B struct B
{ {
this(this) {} this(this) {} // postblit
} }
void main() void main()
{ {
writeln(__traits(hasCopyConstructor, S)); // false writeln(__traits(hasMoveConstructor, S)); // true
writeln(__traits(hasCopyConstructor, C)); // false writeln(__traits(hasMoveConstructor, C)); // false
writeln(__traits(hasCopyConstructor, P)); // true writeln(__traits(hasMoveConstructor, P)); // false
writeln(__traits(hasCopyConstructor, B)); // false, this is a postblit writeln(__traits(hasMoveConstructor, B)); // false, this is a postblit
} }
--- ---
) )
@ -633,13 +676,13 @@ $(H3 $(GNAME initSymbol))
$(P Takes a single argument, which must evaluate to a `class`, `struct` or `union` type. $(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. 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: The slice is constructed for any type `T` as follows:
)
- `ptr` points to either the initializer symbol of `T` - `ptr` points to either the initializer symbol of `T`
or `null` if `T` is a zero-initialized struct / unions. or `null` if `T` is a $(RELATIVE_LINK2 isZeroInit, zero-initialized) struct/union.
- `length` is equal to the size of an instance, i.e. `T.sizeof` for structs / unions and - `length` is equal to the size of an instance, i.e. `T.sizeof` for a struct/union and
$(RELATIVE_LINK2 classInstanceSize, $(D __traits(classInstanceSize, T)`)) for classes. $(RELATIVE_LINK2 classInstanceSize, $(D __traits(classInstanceSize, T))) for a class.
)
$(P $(P
This trait matches the behaviour of `TypeInfo.initializer()` but can also be used when This trait matches the behaviour of `TypeInfo.initializer()` but can also be used when
@ -647,11 +690,14 @@ $(H3 $(GNAME initSymbol))
) )
$(P $(P
This traits is not available during $(DDSUBLINK glossary, ctfe, CTFE) because the actual address This trait is not available during $(DDSUBLINK spec/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. of the initializer symbol will be set by the linker and hence is not available at compile time.
) )
$(SPEC_RUNNABLE_EXAMPLE_RUN
--- ---
import core.stdc.stdlib;
class C class C
{ {
int i = 4; int i = 4;
@ -665,12 +711,14 @@ $(H3 $(GNAME initSymbol))
void* ptr = malloc(initSym.length); void* ptr = malloc(initSym.length);
scope (exit) free(ptr); scope (exit) free(ptr);
ptr[0..initSym.length] = initSym[]; // Note: allocated memory will only be written to through `c`, so cast is safe
ptr[0..initSym.length] = cast(void[]) initSym[];
C c = cast(C) ptr; C c = cast(C) ptr;
assert(c.i == 4); assert(c.i == 4);
} }
--- ---
)
$(H2 $(LNAME2 functions, Function Traits)) $(H2 $(LNAME2 functions, Function Traits))
@ -693,8 +741,8 @@ static assert(!__traits(isDisabled, Foo.bar));
--- ---
) )
$(P For any other declaration even if `@disable` is a syntactically valid $(P For any other declaration, even if `@disable` is a syntactically valid
attribute `false` is returned because the annotation has no effect.) attribute, `false` is returned because the annotation has no effect.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
@ -1076,12 +1124,26 @@ static assert(__traits(getParameterStorageClasses, foo(p, a, b, c), 3)[0] == "la
$(H3 $(GNAME parameters)) $(H3 $(GNAME parameters))
$(P May only be used inside a function. Takes no arguments, and returns $(P May only be used inside a function. Takes no arguments, and returns
a sequence of the enclosing function's parameters.) an $(DDSUBLINK spec/template, lvalue-sequences, lvalue 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.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
alias AliasSeq(A...) = A;
void f(int n, char c)
{
alias PS = __traits(parameters);
PS[0]++; // increment n
static assert(is(typeof(PS) == AliasSeq!(int, char)));
// output parameter names
static foreach (i, p; PS)
{
pragma(msg, __traits(identifier, p));
}
}
int add(int x, int y) int add(int x, int y)
{ {
return x + y; return x + y;
@ -1093,7 +1155,13 @@ $(H3 $(GNAME parameters))
// equivalent to; // equivalent to;
//return add(x, y); //return add(x, y);
} }
---
)
$(P If the function is nested, the parameters returned are those of the
inner function, not the outer one.)
---
int nestedExample(int x) int nestedExample(int x)
{ {
// outer function's parameters // outer function's parameters
@ -1108,7 +1176,8 @@ $(H3 $(GNAME parameters))
return add(x, x); return add(x, x);
} }
---
---
class C class C
{ {
int opApply(int delegate(size_t, C) dg) int opApply(int delegate(size_t, C) dg)
@ -1135,6 +1204,22 @@ $(H3 $(GNAME parameters))
$(H2 $(LNAME2 symbols, Symbol Traits)) $(H2 $(LNAME2 symbols, Symbol Traits))
$(H3 $(GNAME fullyQualifiedName))
$(P Gets the fully qualified name of a type or symbol.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
-----------------
module myModule;
int i;
static assert(__traits(fullyQualifiedName, i) == "myModule.i");
struct MyStruct {}
static assert(__traits(fullyQualifiedName, const MyStruct[]) == "const(myModule.MyStruct[])");
-----------------
)
$(H3 $(GNAME isNested)) $(H3 $(GNAME isNested))
$(P Takes one argument. $(P Takes one argument.
@ -1147,14 +1232,34 @@ $(H3 $(GNAME isNested))
$(H3 $(GNAME isFuture)) $(H3 $(GNAME isFuture))
$(P Takes one argument. It returns `true` if the argument is a symbol $(P Takes one argument. It returns `true` if the argument is a symbol
marked with the `@future` keyword, otherwise `false`. Currently, only marked with the $(DDSUBLINK spec/attribute, future, `@__future` attribute),
functions and variable declarations have support for the `@future` keyword.) otherwise `false`. Currently, only
functions and variable declarations have support for the `@__future` keyword.)
$(H3 $(GNAME isDeprecated)) $(H3 $(GNAME isDeprecated))
$(P Takes one argument. It returns `true` if the argument is a symbol $(P Takes one argument. It returns `true` if the argument is a symbol
marked with the `deprecated` keyword, otherwise `false`.) marked with the `deprecated` keyword, otherwise `false`.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
deprecated("No longer supported")
int i;
struct A
{
int foo() { return 1; }
deprecated("please use foo")
int bar() { return 1; }
}
static assert(__traits(isDeprecated, i));
static assert(!__traits(isDeprecated, A.foo));
static assert(__traits(isDeprecated, A.bar));
---
)
$(H3 $(GNAME isTemplate)) $(H3 $(GNAME isTemplate))
$(P Takes one argument. If that argument or any of its overloads is a template $(P Takes one argument. If that argument or any of its overloads is a template
@ -1164,9 +1269,9 @@ $(H3 $(GNAME isTemplate))
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
void foo(T)(){} void foo(T)(){}
static assert(__traits(isTemplate,foo)); static assert(__traits(isTemplate, foo));
static assert(!__traits(isTemplate,foo!int())); static assert(!__traits(isTemplate, foo!int()));
static assert(!__traits(isTemplate,"string")); static assert(!__traits(isTemplate, "string"));
--- ---
) )
@ -1201,12 +1306,20 @@ $(H3 $(GNAME isPackage))
otherwise $(D false). otherwise $(D false).
) )
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
import std.algorithm.sorting; import std.algorithm.sorting;
static assert(__traits(isPackage, std)); static assert(__traits(isPackage, std));
static assert(__traits(isPackage, std.algorithm)); static assert(__traits(isPackage, std.algorithm));
static assert(!__traits(isPackage, std.algorithm.sorting)); static assert(!__traits(isPackage, std.algorithm.sorting));
--- ---
)
$(H3 $(GNAME isCOMClass))
$(P Takes one argument. If that argument is a symbol that refers to a
$(DDSUBLINK spec/class, ClassDeclaration, class declaration) and is a COM class then $(D true) is retuned,
otherwise $(D false).
)
$(H3 $(GNAME hasMember)) $(H3 $(GNAME hasMember))
@ -1230,11 +1343,12 @@ void main()
{ {
S s; S s;
writeln(__traits(hasMember, S, "m")); // true static assert(__traits(hasMember, S, "m"));
writeln(__traits(hasMember, s, "m")); // true static assert(__traits(hasMember, s, "m"));
writeln(__traits(hasMember, S, "y")); // false static assert(!__traits(hasMember, S, "y"));
writeln(__traits(hasMember, S, "write")); // false, but callable like a member via UFCS static assert(!__traits(hasMember, S, "write")); // false, but callable like a member via UFCS
writeln(__traits(hasMember, int, "sizeof")); // true static assert(__traits(hasMember, int, "sizeof"));
static assert(__traits(hasMember, 5, "sizeof"));
} }
--- ---
) )
@ -1244,13 +1358,10 @@ $(H3 $(GNAME identifier))
$(P Takes one argument, a symbol. Returns the identifier $(P Takes one argument, a symbol. Returns the identifier
for that symbol as a string literal. for that symbol as a string literal.
) )
$(SPEC_RUNNABLE_EXAMPLE_RUN $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
int var = 123; int var = 123;
pragma(msg, typeof(var)); // int static assert(__traits(identifier, var) == "var");
pragma(msg, typeof(__traits(identifier, var))); // string
writeln(var); // 123
writeln(__traits(identifier, var)); // "var"
--- ---
) )
@ -1287,6 +1398,53 @@ tuple((Foo))
) )
) )
$(SECTION3 $(GNAME getBitfieldOffset),
$(P Takes one argument, a qualified name that resolve to a field in a struct or class.
)
$(P If the field is a bitfield, it returns as a `uint` the bit number of the least significant
bit in the field. The rightmost bit is at offset 0, the leftmost bit is at offset 31 (for
32 bit int fields).
)
$(P If the field is a not bitfield, it returns as a `uint` the number 0.
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct S
{
int a,b;
int :2, c:3;
}
static assert(__traits(getBitfieldOffset, S.b) == 0);
static assert(__traits(getBitfieldOffset, S.c) == 2);
---
)
)
$(SECTION3 $(GNAME getBitfieldWidth),
$(P Takes one argument, a qualified name that resolve to a field in a struct or class.
)
$(P If the field is a bitfield, it returns as a `uint` the width of the bit field as
a number of bits.
)
$(P If the field is a not bitfield, it returns the number of bits in the type.
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct S
{
int a,b;
int :2, c:3;
}
static assert(__traits(getBitfieldWidth, S.b) == 32);
static assert(__traits(getBitfieldWidth, S.c) == 3);
---
)
)
$(H3 $(GNAME getLinkage)) $(H3 $(GNAME getLinkage))
$(P Takes one argument, which is a declaration symbol, or the type of a function, delegate, $(P Takes one argument, which is a declaration symbol, or the type of a function, delegate,
@ -1363,13 +1521,13 @@ void main()
$(H3 $(GNAME getOverloads)) $(H3 $(GNAME getOverloads))
$(P The first argument is an aggregate (e.g. struct/class/module). * The first argument is an aggregate type or instance, or a module.
The second argument is a `string` that matches the name of * The second argument is a `string` that matches the name of
the member(s) to return. the member(s) to return.
The third argument is a `bool`, and is optional. If `true`, the * The third argument is a `bool`, and is optional. If `true`, the
result will also include template overloads. result will also include template overloads.
The result is a symbol sequence of all the overloads of the supplied name. * The result is a $(DDSUBLINK spec/template, homogeneous_sequences, symbol sequence)
) of all the overloads of the supplied name.
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
@ -1377,8 +1535,6 @@ import std.stdio;
class D class D
{ {
this() { }
~this() { }
void foo() { } void foo() { }
int foo(int) { return 2; } int foo(int) { return 2; }
void bar(T)() { return T.init; } void bar(T)() { return T.init; }
@ -1389,18 +1545,24 @@ void main()
{ {
D d = new D(); D d = new D();
foreach (t; __traits(getOverloads, D, "foo")) alias fooOverloads = __traits(getOverloads, D, "foo");
writeln(typeid(typeof(t))); foreach (o; fooOverloads)
writeln(typeid(typeof(o)));
alias b = typeof(__traits(getOverloads, D, "foo")); // typeof on a symbol sequence gives a type sequence
foreach (t; b) foreach (T; typeof(fooOverloads))
writeln(typeid(t)); writeln(typeid(T));
auto i = __traits(getOverloads, d, "foo")[1](1); // calls d.foo(3)
writeln(i); auto i = __traits(getOverloads, d, "foo")[1](3);
assert(i == 2);
foreach (t; __traits(getOverloads, D, "bar", true)) // pass true to include templates
writeln(t.stringof); // calls std.stdio.writeln(i)
__traits(getOverloads, std.stdio, "writeln", true)[0](i);
foreach (o; __traits(getOverloads, D, "bar", true))
writeln(o.stringof);
} }
--- ---
) )
@ -1408,10 +1570,10 @@ void main()
Prints: Prints:
$(CONSOLE $(CONSOLE
void() void function()
int() int function(int)
void() void function()
int() int function(int)
2 2
bar(T)() bar(T)()
bar(int n) bar(int n)
@ -1473,6 +1635,43 @@ export
public public
) )
$(H3 $(GNAME fullyQualifiedName))
$(P Takes one argument, which can be a type, expression, or symbol, and returns a string.)
$(UL
$(LI A $(D type) returns a string representing the type.)
$(LI A $(D expression) returns a string representing the type of the expression.)
$(LI A $(D symbol) returns a string representing the fully qualified name of the symbol.)
)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
module plugh;
import std.stdio;
void main()
{
auto s = __traits(fullyQualifiedName, int);
writeln(s);
auto t = __traits(fullyQualifiedName, 1.0);
writeln(t);
auto u = __traits(fullyQualifiedName, t);
writeln(u);
}
---
)
Prints:
$(CONSOLE
int
double
plugh.main.t
)
$(H3 $(GNAME getProtection)) $(H3 $(GNAME getProtection))
$(P A backward-compatible alias for $(GLINK getVisibility).) $(P A backward-compatible alias for $(GLINK getVisibility).)
@ -1507,15 +1706,13 @@ $(H3 $(GNAME getUnitTests))
Takes one argument, a symbol of an aggregate (e.g. struct/class/module). 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 result is a symbol sequence of all the unit test functions of that aggregate.
The functions returned are like normal nested static functions, The functions returned are like normal nested static functions,
$(DDSUBLINK glossary, ctfe, CTFE) will work and $(DDSUBLINK spec/glossary, ctfe, CTFE) will work and
$(DDSUBLINK spec/attribute, uda, UDAs) will be accessible. $(DDSUBLINK spec/attribute, uda, UDAs) will be accessible.
) )
$(H4 Note:) $(NOTE
The `-unittest` flag needs to be passed to the compiler. If the flag
$(P is not passed, $(CODE __traits(getUnitTests)) will always return an
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. empty sequence.
) )
@ -1639,7 +1836,8 @@ $(H3 $(GNAME allMembers))
$(P Takes a single argument, which must evaluate to either $(P Takes a single argument, which must evaluate to either
a module, a struct, a union, a class, an interface, an enum, or a a module, a struct, a union, a class, an interface, an enum, or a
template instantiation. template instantiation.
)
$(P
A sequence of string literals is returned, each of which A sequence of string literals is returned, each of which
is the name of a member of that argument combined with all 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). of the members of its base classes (if the argument is a class).
@ -1730,6 +1928,30 @@ static assert(__traits(isSame, object, object));
alias daz = foo; alias daz = foo;
static assert(__traits(isSame, foo, daz)); static assert(__traits(isSame, foo, daz));
--- ---
)
$(P isSame matches against non-instantiated templates.)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
---
struct Foo(T){
T x;
}
struct Bar(T){
T x;
}
struct Point(T){
T x;
T y;
}
enum isFooOrBar(alias FB) = __traits(isSame, FB, Foo) || __traits(isSame, FB, Bar);
static assert(isFooOrBar!(Foo));
static assert(isFooOrBar!(Bar));
static assert(!isFooOrBar!(Point));
---
) )
$(P The result is `true` if the two arguments are expressions $(P The result is `true` if the two arguments are expressions
@ -1845,14 +2067,27 @@ $(H3 $(GNAME compiles))
compile (are semantically correct). compile (are semantically correct).
The arguments can be symbols, types, or expressions that The arguments can be symbols, types, or expressions that
are syntactically correct. are syntactically correct.
The arguments cannot be statements or declarations. The arguments cannot be statements or declarations - instead
these can be wrapped in a $(DDSUBLINK spec/expression, function_literals,
function literal) expression.
) )
$(P If there are no arguments, the result is $(D false).) $(P If there are no arguments, the result is $(D false).)
$(SPEC_RUNNABLE_EXAMPLE_COMPILE $(SPEC_RUNNABLE_EXAMPLE_COMPILE
--- ---
import std.stdio; static assert(!__traits(compiles));
static assert(__traits(compiles, 1 + 1)); // expression
static assert(__traits(compiles, typeof(1))); // type
static assert(__traits(compiles, object)); // symbol
static assert(__traits(compiles, 1, 2, 3, int, long));
static assert(!__traits(compiles, 3[1])); // semantic error
static assert(!__traits(compiles, 1, 2, 3, int, long, 3[1]));
enum n = 3;
// wrap a declaration/statement in a function literal
static assert(__traits(compiles, { int[n] arr; }));
static assert(!__traits(compiles, { foreach (e; n) {} }));
struct S struct S
{ {
@ -1860,29 +2095,23 @@ struct S
int s2; int s2;
} }
int foo(); static assert(__traits(compiles, S.s1 = 0));
int bar(); static assert(!__traits(compiles, S.s2 = 0));
static assert(!__traits(compiles, S.s3));
void main() int foo();
{
writeln(__traits(compiles)); // false static assert(__traits(compiles, foo));
writeln(__traits(compiles, foo)); // true static assert(__traits(compiles, foo + 1)); // call foo with optional parens
writeln(__traits(compiles, foo + 1)); // true static assert(!__traits(compiles, &foo + 1));
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:) $(P This is useful for:)
$(UL $(UL
$(LI Giving better error messages inside generic code than $(LI Giving better error messages (using $(DDSUBLINK spec/version, static-assert,
`static assert`)) inside generic code than
the sometimes hard to follow compiler ones.) the sometimes hard to follow compiler ones.)
$(LI Doing a finer grained specialization than template $(LI Doing a finer grained specialization than template
partial specialization allows for.) partial specialization allows for.)
@ -1891,5 +2120,5 @@ void main()
$(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling) $(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling)
Macros: Macros:
CHAPTER=25 CHAPTER=26
TITLE=Traits TITLE=Traits

View File

@ -5,8 +5,11 @@ classInstanceAlignment k
classInstanceSize k classInstanceSize k
compiles k compiles k
derivedMembers k derivedMembers k
fullyQualifiedName k
getAliasThis k getAliasThis k
getAttributes k getAttributes k
getBitfieldOffset k
getBitfieldWidth k
getCppNamespaces k getCppNamespaces k
getFunctionAttributes k getFunctionAttributes k
getFunctionVariadicStyle k getFunctionVariadicStyle k
@ -25,6 +28,7 @@ getVirtualMethods k
getVisibility k getVisibility k
hasCopyConstructor k hasCopyConstructor k
hasMember k hasMember k
hasMoveConstructor k
hasPostblit k hasPostblit k
identifier k identifier k
initSymbol k initSymbol k
@ -32,6 +36,7 @@ isAbstractClass k
isAbstractFunction k isAbstractFunction k
isArithmetic k isArithmetic k
isAssociativeArray k isAssociativeArray k
isCOMClass k
isCopyable k isCopyable k
isDeprecated k isDeprecated k
isDisabled k isDisabled k