diff --git a/common/src/dcd/common/constants2.d b/common/src/dcd/common/constants2.d index 65e1a97..044170a 100644 --- a/common/src/dcd/common/constants2.d +++ b/common/src/dcd/common/constants2.d @@ -21,10 +21,12 @@ immutable ConstantCompletion[] pragmas = [ immutable ConstantCompletion[] traits = [ // generated from traits.dd ConstantCompletion("allMembers", `$(P Takes a single argument, which must evaluate to either -a type or an expression of type. -A tuple of string literals is returned, each of which -is the name of a member of that type combined with all -of the members of the base classes (if the type is a class). +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. ) @@ -53,6 +55,59 @@ void main() $(P The order in which the strings appear in the result is not defined.)`), + ConstantCompletion("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 +)`), + ConstantCompletion("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. +)`), ConstantCompletion("classInstanceSize", `$(P Takes a single argument, which must evaluate to either a class type or an expression of class type. The result @@ -109,7 +164,7 @@ partial specialization allows for.) )`), ConstantCompletion("derivedMembers", `$(P Takes a single argument, which must evaluate to either a type or an expression of type. -A tuple of string literals is returned, each of which +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. @@ -139,7 +194,7 @@ void main() $(P The order in which the strings appear in the result is not defined.)`), ConstantCompletion("getAliasThis", `$(P Takes one argument, a type. If the type has ` ~ "`" ~ `alias this` ~ "`" ~ ` declarations, - returns a sequence 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. ) @@ -167,8 +222,8 @@ tuple("var") tuple() )`), ConstantCompletion("getAttributes", `$(P - Takes one argument, a symbol. Returns a tuple of all attached user-defined attributes. - If no UDAs exist it will return an empty tuple. + 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 @@ -196,22 +251,40 @@ tuple(3) tuple("string", 7) tuple((Foo)) ) +)`), + 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. +) +$(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)); +} +--- )`), ConstantCompletion("getFunctionAttributes", `$(P Takes one argument which must either be a function symbol, function literal, - or a function pointer. It returns a string tuple of all the attributes of + 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 $(RELATIVE_LINK2 get-attributes, getAttributes) trait). - If no attributes exist it will return an empty tuple. + 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 tuple is + $(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), and $(D ref))) + $(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 @@ -232,8 +305,6 @@ struct S } pragma(msg, __traits(getFunctionAttributes, S.test)); - -void main(){} --- ) @@ -249,8 +320,6 @@ $(P Note that some attributes can be inferred. For example:) $(SPEC_RUNNABLE_EXAMPLE_COMPILE --- pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; })); - -void main(){} --- ) @@ -260,7 +329,10 @@ $(CONSOLE tuple("pure", "nothrow", "@nogc", "@trusted") ) ) -)`), +) + + +$(H2 $(LNAME2 function-parameters, Function Parameter Traits))`), ConstantCompletion("getFunctionVariadicStyle", `$(P Takes one argument which must either be a function symbol, or a type that is a function, delegate or a function pointer. @@ -329,6 +401,11 @@ static assert(__traits(getLinkage, FooCPPStruct) == "C++"); static assert(__traits(getLinkage, FooCPPClass) == "C++"); static assert(__traits(getLinkage, FooCPPInterface) == "C++"); --- +)`), + ConstantCompletion("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. )`), ConstantCompletion("getMember", `$(P Takes two arguments, the second must be a string. The result is an expression formed from the first @@ -363,7 +440,7 @@ 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 tuple of all the overloads of the supplied name. +The result is a symbol sequence of all the overloads of the supplied name. ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE @@ -413,11 +490,11 @@ bar(int n) )`), ConstantCompletion("getParameterStorageClasses", `$(P Takes two arguments. - The first must either be a function symbol, or a type + 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 tuple of strings representing the storage classes of that parameter. + It returns a *ValueSeq* of strings representing the storage classes of that parameter. ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE @@ -430,6 +507,13 @@ 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"); --- )`), ConstantCompletion("getPointerBitmap", `$(P The argument is a type. @@ -470,39 +554,7 @@ void main() } --- )`), - ConstantCompletion("getProtection", `$(P The argument is a symbol. -The result is a string giving its protection 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(getProtection, d.foo); - writeln(i); - - auto j = __traits(getProtection, d.bar); - writeln(j); -} ---- -) - -Prints: - -$(CONSOLE -export -public -)`), + ConstantCompletion("getProtection", `$(P A backward-compatible alias for $(GLINK getVisibility).)`), ConstantCompletion("getTargetInfo", `$(P Receives a string key as argument. The result is an expression describing the requested target information. ) @@ -520,23 +572,24 @@ 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) )`), ConstantCompletion("getUnitTests", `$(P Takes one argument, a symbol of an aggregate (e.g. struct/class/module). - The result is a tuple 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, $(DDSUBLINK glossary, ctfe, CTFE) will work and $(DDSUBLINK spec/attribute, uda, UDAs) will be accessible. ) -$(H3 Note:) +$(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 tuple. + empty sequence. ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE @@ -612,7 +665,7 @@ a virtual function, $(D -1) is returned instead. class type. The second argument is a string that matches the name of one of the functions of that class. -The result is a tuple of the virtual overloads of that function. +The result is a symbol sequence of the virtual overloads of that function. It does not include final functions that do not override anything. ) @@ -653,6 +706,74 @@ int() void() int() 2 +)`), + ConstantCompletion("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 +)`), + 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. +) + +$(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 +} +--- )`), ConstantCompletion("hasMember", `$(P The first argument is a type that has members, or is an expression of a type that has members. @@ -668,8 +789,6 @@ import std.stdio; struct S { int m; - - import std.stdio; // imports write } void main() @@ -679,18 +798,52 @@ void main() writeln(__traits(hasMember, S, "m")); // true writeln(__traits(hasMember, s, "m")); // true writeln(__traits(hasMember, S, "y")); // false - writeln(__traits(hasMember, S, "write")); // true + writeln(__traits(hasMember, S, "write")); // false, but callable like a member via UFCS writeln(__traits(hasMember, int, "sizeof")); // true } --- +)`), + ConstantCompletion("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 +} +--- )`), ConstantCompletion("identifier", `$(P Takes one argument, a symbol. Returns the identifier for that symbol as a string literal. ) -$(SPEC_RUNNABLE_EXAMPLE_COMPILE +$(SPEC_RUNNABLE_EXAMPLE_RUN --- -import std.stdio; - int var = 123; pragma(msg, typeof(var)); // int pragma(msg, typeof(__traits(identifier, var))); // string @@ -698,6 +851,50 @@ 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. + 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))`), 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) is returned. @@ -766,6 +963,8 @@ 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; @@ -791,6 +990,24 @@ false )`), ConstantCompletion("isAssociativeArray", `$(P Works like $(D isArithmetic), except it's for associative array types.)`), + ConstantCompletion("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)); +--- +)`), ConstantCompletion("isDeprecated", `$(P Takes one argument. It returns ` ~ "`" ~ `true` ~ "`" ~ ` if the argument is a symbol marked with the ` ~ "`" ~ `deprecated` ~ "`" ~ ` keyword, otherwise ` ~ "`" ~ `false` ~ "`" ~ `.)`), ConstantCompletion("isDisabled", `$(P Takes one argument and returns ` ~ "`" ~ `true` ~ "`" ~ ` if it's a function declaration @@ -854,8 +1071,17 @@ void main() } --- )`), - ConstantCompletion("isFloating", `$(P Works like $(D isArithmetic), except it's for floating -point types (including imaginary and complex types).) + ConstantCompletion("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 --- @@ -864,8 +1090,6 @@ import core.simd : float4; enum E : float { a, b } static assert(__traits(isFloating, float)); -static assert(__traits(isFloating, idouble)); -static assert(__traits(isFloating, creal)); static assert(__traits(isFloating, E)); static assert(__traits(isFloating, float4)); @@ -875,8 +1099,16 @@ static assert(!__traits(isFloating, float[4])); ConstantCompletion("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.)`), - ConstantCompletion("isIntegral", `$(P Works like $(D isArithmetic), except it's for integral -types (including character 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) +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 --- @@ -923,6 +1155,27 @@ void foolazy(lazy int x) static assert(__traits(isLazy, x)); } --- +)`), + ConstantCompletion("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)); +--- )`), ConstantCompletion("isNested", `$(P Takes one argument. It returns $(D true) if the argument is a nested type which internally @@ -988,6 +1241,17 @@ void main() )`), 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).)`), + 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, +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)); +---`), 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), or $(D_KEYWORD lazy), otherwise $(D false). @@ -1049,34 +1313,42 @@ $(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.) ))`), - ConstantCompletion("isSame", `$(P Takes two arguments and returns bool $(D true) if they -are the same symbol, $(D false) if not.) + ConstantCompletion("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 --- -import std.stdio; - struct S { } int foo(); int bar(); -void main() -{ - writeln(__traits(isSame, foo, foo)); // true - writeln(__traits(isSame, foo, bar)); // false - writeln(__traits(isSame, foo, S)); // false - writeln(__traits(isSame, S, S)); // true - writeln(__traits(isSame, std, S)); // false - writeln(__traits(isSame, std, std)); // true -} +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 If the two arguments are expressions made up of literals -or enums that evaluate to the same value, true is returned.) +$(P The result is ` ~ "`" ~ `true` ~ "`" ~ ` if the two arguments are expressions +made up of literals or enums that evaluate to the same value.) -$(P If the two arguments are both lambda functions (or aliases +$(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:) @@ -1093,11 +1365,20 @@ statements, the function is considered incomparable.) ) $(P If these constraints aren't fulfilled, the function is considered -incomparable and ` ~ "`" ~ `isSame` ~ "`" ~ ` returns $(D false).) +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() @@ -1106,11 +1387,6 @@ void test(alias pred)() void main() { - 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)); - // lambdas accessing local variables are considered incomparable int b; static assert(!__traits(isSame, a => a + b, a => a + b)); @@ -1119,34 +1395,65 @@ void main() 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; - } +int a; +this(int a) +{ + this.a = a; +} } class B { - int a; - this(int a) - { - this.a = a; - } +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))); --- )`), - ConstantCompletion("isScalar", `$(P Works like $(D isArithmetic), except it's for scalar -types.) + ConstantCompletion("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 --- @@ -1207,8 +1514,8 @@ void main() } --- )`), - ConstantCompletion("isTemplate", `$(P Takes one argument. If that argument is a template then $(D true) is returned, -otherwise $(D false). + ConstantCompletion("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 @@ -1219,8 +1526,16 @@ static assert(!__traits(isTemplate,foo!int())); static assert(!__traits(isTemplate,"string")); --- )`), - ConstantCompletion("isUnsigned", `$(P Works like $(D isArithmetic), except it's for unsigned -types.) + ConstantCompletion("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 --- @@ -1295,9 +1610,90 @@ void test() class C { int x = -1; } static assert(__traits(isZeroInit, C)); + +// For initializing arrays of element type ` ~ "`" ~ `void` ~ "`" ~ `. +static assert(__traits(isZeroInit, void)); --- )`), + ConstantCompletion("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))`), ConstantCompletion("parent", `$(P Takes a single argument which must evaluate to a symbol. The result is the symbol that is the parent of it. )`), + ConstantCompletion("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.)`), ]; diff --git a/constants-gen/pragma.dd b/constants-gen/pragma.dd index 0f3be23..f8516f6 100644 --- a/constants-gen/pragma.dd +++ b/constants-gen/pragma.dd @@ -5,23 +5,29 @@ $(SPEC_S Pragmas, $(HEADERNAV_TOC) $(GRAMMAR +$(GNAME PragmaDeclaration): + $(GLINK Pragma) $(D ;) + $(GLINK Pragma) $(GLINK2 attribute, DeclarationBlock) + +$(GNAME PragmaStatement): + $(GLINK Pragma) $(D ;) + $(GLINK Pragma) $(GLINK2 statement, NoScopeStatement) + $(GNAME Pragma): $(D pragma) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D $(RPAREN)) $(D pragma) $(D $(LPAREN)) $(GLINK_LEX Identifier) $(D ,) $(GLINK2 expression, ArgumentList) $(D $(RPAREN)) ) - $(P Pragmas are a way to pass special information to the compiler - and to add vendor specific extensions to D. - Pragmas can be used by themselves terminated with a $(SINGLEQUOTE ;), - they can influence a statement, a block of statements, a declaration, or + $(P Pragmas pass special information to the implementation + and can add vendor specific extensions. + Pragmas can be used by themselves terminated with a $(TT ;), + and can apply to a statement, a block of statements, a declaration, or a block of declarations. ) - $(P Pragmas can appear as either declarations, - $(I Pragma) $(GLINK2 attribute, DeclarationBlock), - or as statements, - $(GLINK2 statement, PragmaStatement). + $(P Pragmas can be either a $(GLINK PragmaDeclaration) + or a $(GLINK PragmaStatement). ) ----------------- @@ -60,23 +66,143 @@ $(H2 $(LEGACY_LNAME2 Predefined-Pragmas, predefined-pragmas, Predefined Pragmas) $(P All implementations must support these, even if by just ignoring them:) $(UL + $(LI $(LINK2 #crtctor, pragma crt$(UNDERSCORE)constructor)) + $(LI $(LINK2 #crtdtor, pragma crt$(UNDERSCORE)destructor)) $(LI $(LINK2 #inline, pragma inline)) $(LI $(LINK2 #lib, pragma lib)) $(LI $(LINK2 #linkerDirective, pragma linkerDirective)) $(LI $(LINK2 #mangle, pragma mangle)) $(LI $(LINK2 #msg, pragma msg)) + $(LI $(LINK2 #printf, pragma printf)) + $(LI $(LINK2 #scanf, pragma scanf)) $(LI $(LINK2 #startaddress, pragma startaddress)) ) $(IMPLEMENTATION_DEFINED An implementation may ignore these pragmas.) +$(H3 $(LNAME2 crtctor, $(D pragma crt_constructor))) + + $(P Annotates a function so it is run after the C runtime library is initialized + and before the D runtime library is initialized. + ) + + $(P The function must:) + + $(OL + $(LI be `extern (C)`) + $(LI not have any parameters) + $(LI not be a non-static member function) + $(LI be a function definition, not a declaration (i.e. it must have a function body)) + $(LI not return a type that has a destructor) + $(LI not be a nested function) + ) + + --- + __gshared int initCount; + + pragma(crt_constructor) + extern(C) void initializer() { initCount += 1; } + --- + + $(P No arguments to the pragma are allowed.) + + $(P A function may be annotated with both `pragma(crt_constructor)` + and `pragma(crt_destructor)`. + ) + + $(P Annotating declarations other than function definitions has no effect.) + + $(P Annotating a struct or class definition does not affect the members of + the aggregate.) + + $(P A function that is annotated with `pragma(crt_constructor)` may initialize + `const` or `immutable` variables.) + + $(BEST_PRACTICE Use for system programming and interfacing with C/C++, + for example to allow for initialization of the runtime when loading a DSO, + or as a simple replacement for `shared static this` in + $(DDLINK spec/betterc, betterC mode, betterC mode). + ) + + $(IMPLEMENTATION_DEFINED The order in which functions annotated with `pragma(crt_constructor)` + are run is implementation defined. + ) + + $(BEST_PRACTICE to control the order in which the functions are called within one module, write + a single function that calls them in the desired order, and only annotate that function. + ) + + $(IMPLEMENTATION_DEFINED This uses the mechanism C compilers use to run + code before `main()` is called. C++ compilers use it to run static + constructors and destructors. + For example, GCC's $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html, `__attribute__((constructor))`) + is equivalent. + Digital Mars C uses $(TT _STI) and $(TT _STD) identifier prefixes to mark crt_constructor and crt_destructor functions. + ) + + $(IMPLEMENTATION_DEFINED + A reference to the annotated function will be inserted in + the $(TT .init_array) section for Elf systems, + the $(TT XI) section for Win32 OMF systems, + the $(TT .CRT$XCU) section for Windows MSCOFF systems, + and the $(TT __mod_init_func) section for OSX systems. + ) + + $(NOTE `crt_constructor` and `crt_destructor` were implemented in + $(LINK2 $(ROOT_DIR)changelog/2.078.0.html, v2.078.0 (2018-01-01)). + Some compilers exposed non-standard, compiler-specific mechanism before. + ) + +$(H3 $(LNAME2 crtdtor, $(D pragma crt_destructor))) + + $(P `pragma(crt_destructor)` works the same as `pragma(crt_constructor)` except:) + + $(OL + $(LI Annotates a function so it is run after the D runtime library is terminated + and before the C runtime library is terminated. + Calling C's `exit()` function also causes the annotated functions to run.) + $(LI The order in which the annotated functions are run is the reverse of those functions + annotated with `pragma(crt_constructor)`.) + ) + + $(IMPLEMENTATION_DEFINED This uses the mechanism C compilers use to run + code after `main()` returns or `exit()` is called. C++ compilers use it to run static + destructors. + For example, GCC's $(LINK2 https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html, `__attribute__((destructor))`) + is equivalent. + Digital Mars C uses $(TT _STI) and $(TT _STD) identifier prefixes to mark crt_constructor and crt_destructor functions. + ) + + $(IMPLEMENTATION_DEFINED + A reference to the annotated function will be inserted in + the $(TT .fini_array) section for Elf systems, + the $(TT XC) section for Win32 OMF systems, + the $(TT .CRT$XPU) section for Windows MSCOFF systems, + and the $(TT __mod_term_func) section for OSX systems. + ) + +--- +__gshared int initCount; + +pragma(crt_constructor) +extern(C) void initialize() { initCount += 1; } + +pragma(crt_destructor) +extern(C) void deinitialize() { initCount -= 1; } + +pragma(crt_constructor) +pragma(crt_destructor) +extern(C) void innuendo() { printf("Inside a constructor... Or destructor?\n"); } +--- + + $(H3 $(LNAME2 inline, $(D pragma inline))) $(P Affects whether functions are inlined or not. If at the declaration level, it affects the functions declared in the block it controls. If inside a function, it affects the function it is enclosed by.) - $(P It takes three forms:) + $(P It takes two forms:) $(OL $(LI --- @@ -86,21 +212,15 @@ pragma(inline) ) $(LI --- -pragma(inline, false) +pragma(inline, AssignExpression) --- - Functions are never inlined. - ) - $(LI ---- -pragma(inline, true) ---- - Always inline the functions. + The $(GLINK2 expression, AssignExpression) is evaluated and must have a type that can be converted + to a boolean. + If the result is false the functions are never inlined, otherwise they are always inlined. ) ) - $(P There can be only zero or one $(I AssignExpression)s. If one is there, it must - be `true`, `false`, or an integer value. An integer value is implicitly converted - to a bool.) + $(P More than one $(I AssignExpression) is not allowed.) $(P If there are multiple pragma inlines in a function, the lexically last one takes effect.) @@ -133,8 +253,8 @@ pragma(lib, "foo.lib"); ----------------- $(IMPLEMENTATION_DEFINED - Typically, the string literal specifies the file name of a library file. This name - is inserted into the generated object file, or otherwise is passed to the linker, + The string literal specifies the file name of a library file. This name + is inserted into the generated object file, or otherwise passed to the linker, so the linker automatically links in that library. ) @@ -147,44 +267,177 @@ pragma(linkerDirective, "/FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=2"); ----------------- $(IMPLEMENTATION_DEFINED - $(P The string literal specifies a linker directive to be embedded in the generated object file.) - - $(P Linker directives are only supported for MS-COFF output.) + The string literal specifies a linker directive to be embedded in the generated object file. + Linker directives are only supported for MS-COFF output. ) $(H3 $(LNAME2 mangle, $(D pragma mangle))) $(P Overrides the default mangling for a symbol.) - $(P There must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal. + $(P For variables and functions there must be one $(ASSIGNEXPRESSION) and it must evaluate at compile time to a string literal. + For aggregates there may be one or two $(ASSIGNEXPRESSION)s, one of which must evaluate at compile time to a string literal and + one which must evaluate to a symbol. If that symbol is a $(I TemplateInstance), the aggregate is treated as a template + that has the signature and arguments of the $(I TemplateInstance). The identifier of the symbol is used when no string is supplied. + Both arguments may be used used when an aggregate's name is a D keyword. ) + $(P It only applies to function and variable symbols. Other symbols are ignored.) + $(IMPLEMENTATION_DEFINED On macOS and Win32, an extra underscore (`_`) is prepended to the string since 2.079, as is done by the C/C++ toolchain. This allows using the same `pragma(mangle)` for all compatible (POSIX in one case, win64 in another) platforms instead of having to special-case. ) - $(IMPLEMENTATION_DEFINED It's only effective - when the symbol is a function declaration or a variable declaration. - For example this allows linking to a symbol which is a D keyword, which would normally - be disallowed as a symbol name: + $(RATIONALE + $(UL + $(LI Enables linking to symbol names that D cannot represent.) + $(LI Enables linking to a symbol which is a D keyword, since an $(GLINK_LEX Identifier) + cannot be a keyword.) + ) + --- + pragma(mangle, "body") + extern(C) void body_func(); + pragma(mangle, "function") + extern(C++) struct _function {} + template ScopeClass(C) + { + pragma(mangle, C.stringof, C) + struct ScopeClass { align(__traits(classInstanceAlignment, C)) void[__traits(classInstanceSize, C)] buffer; } + } + extern(C++) + { + class MyClassA(T) {} + void func(ref ScopeClass!(MyClassA!int)); // mangles as MyClass& + } + --- ) ------------------ -pragma(mangle, "body") -extern(C) void body_func(); ------------------ $(H3 $(LNAME2 msg, $(D pragma msg))) - $(P Constructs a message from the $(I ArgumentList).) + $(P Each $(ASSIGNEXPRESSION) is evaluated at compile time and then all are combined into a message.) + + --- + pragma(msg, "compiling...", 6, 1.0); // prints "compiling...61.0" at compile time + --- + + $(IMPLEMENTATION_DEFINED The form the message takes and how it is presented to the user. + One way is by printing them to the standard error stream.) + + $(RATIONALE Analogously to how `writeln()` performs a role of writing informational messages during runtime, + `pragma(msg)` performs the equivalent role at compile time. + For example, + --- + static if (kilroy) + pragma(msg, "Kilroy was here"); + else + pragma(msg, "Kilroy got lost"); + --- + ) + +$(H3 $(LNAME2 printf, $(D pragma printf))) + + $(P `pragma(printf)` specifies that a function declaration is a printf-like function, meaning + it is an `extern (C)` or `extern (C++)` function with a `format` parameter accepting a + pointer to a 0-terminated `char` string conforming to the C99 Standard 7.19.6.1, immediately followed + by either a `...` variadic argument list or a parameter of type `va_list` as the last parameter. + ) + + $(P If the `format` argument is a string literal, it is verified to be a valid format string + per the C99 Standard. If the `format` parameter is followed by `...`, the number and types + of the variadic arguments are checked against the format string.) + + $(P Diagnosed incompatibilities are:) + + $(UL + $(LI incompatible sizes which may cause argument misalignment) + $(LI deferencing arguments that are not pointers) + $(LI insufficient number of arguments) + $(LI struct arguments) + $(LI array and slice arguments) + $(LI non-pointer arguments to `s` specifier) + $(LI non-standard formats) + $(LI undefined behavior per C99) + ) + + $(P Per the C99 Standard, extra arguments are ignored.) + + $(P Ignored mismatches are:) + + $(UL + $(LI sign mismatches, such as printing an `int` with a `%u` format) + $(LI integral promotion mismatches, where the format specifies a smaller integral + type than `int` or `uint`, such as printing a `short` with the `%d` format rather than `%hd`) + ) + + --- + printf("%k\n", value); // error: non-Standard format k + printf("%d\n"); // error: not enough arguments + printf("%d\n", 1, 2); // ok, extra arguments ignored + --- + + $(BEST_PRACTICE + In order to use non-Standard printf/scanf formats, an easy workaround is: + --- + const format = "%k\n"; + printf(format.ptr, value); // no error + --- + ) + + $(BEST_PRACTICE + Most of the errors detected are portability issues. For instance, + + --- + string s; + printf("%.*s\n", s.length, s.ptr); + printf("%d\n", s.sizeof); + ulong u; + scanf("%lld%*c\n", &u); + --- + should be replaced with: + --- + string s; + printf("%.*s\n", cast(int) s.length, s.ptr); + printf("%zd\n", s.sizeof); + ulong u; + scanf("%llu%*c\n", &u); + --- + ) + + $(P `pragma(printf)` applied to declarations that are not functions are ignored. + In particular, it has no effect on the declaration of a pointer to function type. + ) + + +$(H3 $(LNAME2 scanf, $(D pragma scanf))) + + $(P `pragma(scanf)` specifies that a function declaration is a scanf-like function, meaning + it is an `extern (C)` or `extern (C++)` function with a `format` parameter accepting a + pointer to a 0-terminated `char` string conforming to the C99 Standard 7.19.6.2, immediately followed + by either a `...` variadic argument list or a parameter of type `va_list` as the last parameter. + ) + + $(P If the `format` argument is a string literal, it is verified to be a valid format string + per the C99 Standard. If the `format` parameter is followed by `...`, the number and types + of the variadic arguments are checked against the format string.) + + $(P Diagnosed incompatibilities are:) + + $(UL + $(LI argument is not a pointer to the format specified type) + $(LI insufficient number of arguments) + $(LI non-standard formats) + $(LI undefined behavior per C99) + ) + + $(P Per the C99 Standard, extra arguments are ignored.) + + $(P `pragma(scanf)` applied to declarations that are not functions are ignored. + In particular, it has no effect on the declaration of a pointer to function type. + ) ------------------ -pragma(msg, "compiling...", 1, 1.0); ------------------ - $(IMPLEMENTATION_DEFINED The arguments are typically presented to the user during compilation, - such as by printing them to the standard error stream.) $(H3 $(LNAME2 startaddress, $(D pragma startaddress))) diff --git a/constants-gen/traits.dd b/constants-gen/traits.dd index dbd2c6d..888b05c 100644 --- a/constants-gen/traits.dd +++ b/constants-gen/traits.dd @@ -4,6 +4,8 @@ $(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 @@ -18,66 +20,82 @@ $(GNAME TraitsExpression): $(D __traits) $(D $(LPAREN)) $(GLINK TraitsKeyword) $(D ,) $(GLINK TraitsArguments) $(D $(RPAREN)) $(GNAME TraitsKeyword): - $(GLINK isAbstractClass) - $(GLINK isArithmetic) - $(GLINK isAssociativeArray) - $(GLINK isFinalClass) - $(GLINK isPOD) - $(GLINK isNested) - $(GLINK isFuture) - $(GLINK isDeprecated) - $(GLINK isFloating) - $(GLINK isIntegral) - $(GLINK isScalar) - $(GLINK isStaticArray) - $(GLINK isUnsigned) - $(GLINK isDisabled) - $(GLINK isVirtualFunction) - $(GLINK isVirtualMethod) - $(GLINK isAbstractFunction) - $(GLINK isFinalFunction) - $(GLINK isStaticFunction) - $(GLINK isOverrideFunction) - $(GLINK isTemplate) - $(GLINK isRef) - $(GLINK isOut) - $(GLINK isLazy) - $(GLINK isReturnOnStack) - $(GLINK isZeroInit) - $(GLINK hasMember) - $(GLINK identifier) - $(GLINK getAliasThis) - $(GLINK getAttributes) - $(GLINK getFunctionAttributes) - $(GLINK getFunctionVariadicStyle) - $(GLINK getLinkage) - $(GLINK getMember) - $(GLINK getOverloads) - $(GLINK getParameterStorageClasses) - $(GLINK getPointerBitmap) - $(GLINK getProtection) - $(GLINK getTargetInfo) - $(GLINK getVirtualFunctions) - $(GLINK getVirtualMethods) - $(GLINK getUnitTests) - $(GLINK parent) - $(GLINK classInstanceSize) - $(GLINK getVirtualIndex) - $(GLINK allMembers) - $(GLINK derivedMembers) - $(GLINK isSame) - $(GLINK compiles) + $(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 ,) $(I TraitsArguments) + $(GLINK TraitsArgument) $(D ,) $(GSELF TraitsArguments) $(GNAME TraitsArgument): $(GLINK2 expression, AssignExpression) - $(GLINK2 declaration, Type) + $(GLINK2 type, Type) ) -$(H2 $(GNAME isArithmetic)) + +$(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) @@ -85,6 +103,8 @@ $(H2 $(GNAME isArithmetic)) 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; @@ -109,10 +129,19 @@ false false ) -$(H2 $(GNAME isFloating)) +$(H3 $(GNAME isFloating)) - $(P Works like $(D isArithmetic), except it's for floating - point types (including imaginary and complex types).) + $(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 --- @@ -121,8 +150,6 @@ import core.simd : float4; enum E : float { a, b } static assert(__traits(isFloating, float)); -static assert(__traits(isFloating, idouble)); -static assert(__traits(isFloating, creal)); static assert(__traits(isFloating, E)); static assert(__traits(isFloating, float4)); @@ -130,10 +157,18 @@ static assert(!__traits(isFloating, float[4])); --- ) -$(H2 $(GNAME isIntegral)) +$(H3 $(GNAME isIntegral)) - $(P Works like $(D isArithmetic), except it's for integral - types (including character types).) + $(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 --- @@ -153,10 +188,19 @@ static assert(!__traits(isIntegral, void*)); --- ) -$(H2 $(GNAME isScalar)) +$(H3 $(GNAME isScalar)) - $(P Works like $(D isArithmetic), except it's for scalar - types.) + $(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 --- @@ -180,10 +224,18 @@ static assert(!__traits(isScalar, Object)); --- ) -$(H2 $(GNAME isUnsigned)) +$(H3 $(GNAME isUnsigned)) - $(P Works like $(D isArithmetic), except it's for unsigned - types.) + $(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 --- @@ -206,7 +258,7 @@ static assert(!__traits(isUnsigned, void*)); --- ) -$(H2 $(GNAME isStaticArray)) +$(H3 $(GNAME isStaticArray)) $(P Works like $(D isArithmetic), except it's for static array types.) @@ -226,12 +278,12 @@ static assert(!__traits(isStaticArray, array)); --- ) -$(H2 $(GNAME isAssociativeArray)) +$(H3 $(GNAME isAssociativeArray)) $(P Works like $(D isArithmetic), except it's for associative array types.) -$(H2 $(GNAME isAbstractClass)) +$(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) @@ -265,37 +317,365 @@ false false ) -$(H2 $(GNAME isFinalClass)) +$(H3 $(GNAME isFinalClass)) $(P Works like $(D isAbstractClass), except it's for final classes.) -$(H2 $(GNAME isPOD)) +$(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).) -$(H2 $(GNAME isNested)) +$(H3 $(GNAME toType)) - $(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).) + $(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.) -$(H2 $(GNAME isFuture)) + $(P Only D mangling is supported. Other manglings, such as C++ mangling, are not.) - $(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.) + $(P The value returned is a type.) -$(H2 $(GNAME isDeprecated)) + --- + template Type(T) { alias Type = T; } - $(P Takes one argument. It returns `true` if the argument is a symbol - marked with the `deprecated` keyword, otherwise `false`.) + Type!(__traits(toType, "i")) j = 3; // j is declared as type `int` -$(H2 $(GNAME isDisabled)) + 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`.) @@ -324,13 +704,22 @@ static assert(!__traits(isDisabled, Bar)); --- ) -$(H2 $(GNAME isVirtualFunction)) +$(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. ) -$(H2 $(GNAME isVirtualMethod)) +$(H3 $(GNAME isVirtualMethod)) $(P Takes one argument. If that argument is a virtual function, $(D true) is returned, otherwise $(D false). @@ -359,7 +748,7 @@ void main() --- ) -$(H2 $(GNAME isAbstractFunction)) +$(H3 $(GNAME isAbstractFunction)) $(P Takes one argument. If that argument is an abstract function, $(D true) is returned, otherwise $(D false). @@ -393,7 +782,7 @@ void main() --- ) -$(H2 $(GNAME isFinalFunction)) +$(H3 $(GNAME isFinalFunction)) $(P Takes one argument. If that argument is a final function, $(D true) is returned, otherwise $(D false). @@ -429,7 +818,7 @@ void main() --- ) -$(H2 $(GNAME isOverrideFunction)) +$(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). @@ -459,7 +848,7 @@ void main() --- ) -$(H2 $(GNAME isStaticFunction)) +$(H3 $(GNAME isStaticFunction)) $(P Takes one argument. If that argument is a static function, meaning it has no context pointer, @@ -483,83 +872,7 @@ void main() --- ) -$(H2 $(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)); -} ---- -) - -$(H2 $(GNAME isTemplate)) - - $(P Takes one argument. If that argument 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")); ---- -) - -$(H2 $(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)); ---- -) - -$(H2 $(GNAME isReturnOnStack)) +$(H3 $(GNAME isReturnOnStack)) $(P Takes one argument which must either be a function symbol, function literal, @@ -594,121 +907,7 @@ $(SPEC_RUNNABLE_EXAMPLE_COMPILE this enables efficient, direct, and simple testing.) )) -$(H2 $(GNAME hasMember)) - - $(P The first argument is a type that has members, or - is an expression of a type that has members. - The second argument is a string. - If the string is a valid property of the type, - $(D true) is returned, otherwise $(D false). - ) - -$(SPEC_RUNNABLE_EXAMPLE_COMPILE ---- -import std.stdio; - -struct S -{ - int m; - - import std.stdio; // imports write -} - -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")); // true - writeln(__traits(hasMember, int, "sizeof")); // true -} ---- -) - -$(H2 $(GNAME identifier)) - - $(P Takes one argument, a symbol. Returns the identifier - for that symbol as a string literal. - ) -$(SPEC_RUNNABLE_EXAMPLE_COMPILE ---- -import std.stdio; - -int var = 123; -pragma(msg, typeof(var)); // int -pragma(msg, typeof(__traits(identifier, var))); // string -writeln(var); // 123 -writeln(__traits(identifier, var)); // "var" ---- -) - -$(H2 $(GNAME getAliasThis)) - - $(P Takes one argument, a type. If the type has `alias this` declarations, - returns a sequence 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() -) - -$(SECTION2 $(GNAME getAttributes), - $(P - Takes one argument, a symbol. Returns a tuple of all attached user-defined attributes. - If no UDAs exist it will return an empty tuple. - ) - - $(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)) -) -) - -$(SECTION2 $(GNAME getFunctionVariadicStyle), +$(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. @@ -746,22 +945,22 @@ static assert(__traits(getFunctionVariadicStyle, typeof(cstyle)) == "stdarg"); ) ) -$(SECTION2 $(GNAME getFunctionAttributes), +$(SECTION3 $(GNAME getFunctionAttributes), $(P Takes one argument which must either be a function symbol, function literal, - or a function pointer. It returns a string tuple of all the attributes of + 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 $(RELATIVE_LINK2 get-attributes, getAttributes) trait). - If no attributes exist it will return an empty tuple. + 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 tuple is + $(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), and $(D ref))) + $(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 @@ -782,8 +981,6 @@ struct S } pragma(msg, __traits(getFunctionAttributes, S.test)); - -void main(){} --- ) @@ -799,8 +996,6 @@ tuple("const", "@system") $(SPEC_RUNNABLE_EXAMPLE_COMPILE --- pragma(msg, __traits(getFunctionAttributes, (int x) @trusted { return x * 2; })); - -void main(){} --- ) @@ -812,7 +1007,287 @@ tuple("pure", "nothrow", "@nogc", "@trusted") ) ) -$(H2 $(GNAME getLinkage)) + +$(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. @@ -848,7 +1323,14 @@ static assert(__traits(getLinkage, FooCPPInterface) == "C++"); --- ) -$(H2 $(GNAME getMember)) +$(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 @@ -879,14 +1361,14 @@ void main() --- ) -$(H2 $(GNAME getOverloads)) +$(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 tuple of all the overloads of the supplied name. + The result is a symbol sequence of all the overloads of the supplied name. ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE @@ -935,76 +1417,30 @@ bar(T)() bar(int n) ) -$(H2 $(GNAME getParameterStorageClasses)) - - $(P - Takes two arguments. - The first must either be a function symbol, 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 tuple of strings representing the storage classes of that parameter. +$(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 ---- -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"); ---- -) - -$(H2 $(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 --- +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 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]); + static assert(__traits(getCppNamespaces, Foo)[0] == "ns"); + static assert(!__traits(getCppNamespaces, Bar).length); + static assert(__traits(getCppNamespaces, Foo) == __traits(getCppNamespaces, Baz)); } --- ) - -$(H2 $(GNAME getProtection)) +$(H3 $(GNAME getVisibility)) $(P The argument is a symbol. - The result is a string giving its protection level: "public", "private", "protected", "export", or "package". + The result is a string giving its visibility level: "public", "private", "protected", "export", or "package". ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE @@ -1021,10 +1457,10 @@ void main() { D d = new D(); - auto i = __traits(getProtection, d.foo); + auto i = __traits(getVisibility, d.foo); writeln(i); - auto j = __traits(getProtection, d.bar); + auto j = __traits(getVisibility, d.bar); writeln(j); } --- @@ -1037,7 +1473,11 @@ export public ) -$(H2 $(GNAME getTargetInfo)) +$(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. @@ -1056,81 +1496,27 @@ version (CppRuntime_Microsoft) $(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) ) -$(H2 $(GNAME getVirtualFunctions)) - - $(P The same as $(GLINK getVirtualMethods), except that - final functions that do not override anything are included. - ) - -$(H2 $(GNAME getVirtualMethods)) - - $(P The first argument is a class type or an expression of - class type. - The second argument is a string that matches the name of - one of the functions of that class. - The result is a tuple of the virtual overloads of that function. - It does not include final functions that do not override anything. - ) - -$(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 -) - -$(H2 $(GNAME getUnitTests)) +$(H3 $(GNAME getUnitTests)) $(P Takes one argument, a symbol of an aggregate (e.g. struct/class/module). - The result is a tuple 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, $(DDSUBLINK glossary, ctfe, CTFE) will work and $(DDSUBLINK spec/attribute, uda, UDAs) will be accessible. ) - $(H3 Note:) + $(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 tuple. + empty sequence. ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE @@ -1194,39 +1580,69 @@ foo.unittest foo.Foo.unittest ) -$(H2 $(GNAME parent)) +$(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. ) -$(H2 $(GNAME classInstanceSize)) +$(H3 $(GNAME child)) - $(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. + $(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. ) -$(H2 $(GNAME getVirtualIndex)) +$(SPEC_RUNNABLE_EXAMPLE_COMPILE +--- +import std.stdio; - $(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. - ) +struct A +{ + int i; + int foo(int j) { + return i * j; + } + T bar(T)(T t) { + return i + t; + } +} -$(H2 $(GNAME allMembers)) +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 type or an expression of type. - A tuple of string literals is returned, each of which - is the name of a member of that type combined with all - of the members of the base classes (if the type is a class). + 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. ) @@ -1256,11 +1672,11 @@ void main() $(P The order in which the strings appear in the result is not defined.) -$(H2 $(GNAME derivedMembers)) +$(H3 $(GNAME derivedMembers)) $(P Takes a single argument, which must evaluate to either a type or an expression of type. - A tuple of string literals is returned, each of which + 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. @@ -1290,36 +1706,44 @@ void main() $(P The order in which the strings appear in the result is not defined.) -$(H2 $(GNAME isSame)) +$(H3 $(GNAME isSame)) - $(P Takes two arguments and returns bool $(D true) if they - are the same symbol, $(D false) if not.) + $(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 --- -import std.stdio; - struct S { } int foo(); int bar(); -void main() -{ - writeln(__traits(isSame, foo, foo)); // true - writeln(__traits(isSame, foo, bar)); // false - writeln(__traits(isSame, foo, S)); // false - writeln(__traits(isSame, S, S)); // true - writeln(__traits(isSame, std, S)); // false - writeln(__traits(isSame, std, std)); // true -} +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 If the two arguments are expressions made up of literals - or enums that evaluate to the same value, true is returned.) + $(P The result is `true` if the two arguments are expressions + made up of literals or enums that evaluate to the same value.) - $(P If the two arguments are both lambda functions (or aliases +$(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:) @@ -1336,11 +1760,20 @@ void main() ) $(P If these constraints aren't fulfilled, the function is considered - incomparable and `isSame` returns $(D false).) + 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() @@ -1349,11 +1782,6 @@ void test(alias pred)() void main() { - 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)); - // lambdas accessing local variables are considered incomparable int b; static assert(!__traits(isSame, a => a + b, a => a + b)); @@ -1362,7 +1790,11 @@ void main() 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; @@ -1385,11 +1817,29 @@ void main() // 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))); --- ) -$(H2 $(GNAME compiles)) +$(H3 $(GNAME compiles)) $(P Returns a bool $(D true) if all of the arguments compile (are semantically correct). @@ -1438,10 +1888,7 @@ void main() partial specialization allows for.) ) - - $(SPEC_SUBNAV_PREV_NEXT version, Conditional Compilation, errors, Error Handling) -) Macros: CHAPTER=25 diff --git a/tests/tc_traits/expected.txt b/tests/tc_traits/expected.txt index eb3ae69..631b258 100644 --- a/tests/tc_traits/expected.txt +++ b/tests/tc_traits/expected.txt @@ -1,13 +1,17 @@ identifiers allMembers k +child k +classInstanceAlignment k classInstanceSize k compiles k derivedMembers k getAliasThis k getAttributes k +getCppNamespaces k getFunctionAttributes k getFunctionVariadicStyle k getLinkage k +getLocation k getMember k getOverloads k getParameterStorageClasses k @@ -18,12 +22,17 @@ getUnitTests k getVirtualFunctions k getVirtualIndex k getVirtualMethods k +getVisibility k +hasCopyConstructor k hasMember k +hasPostblit k identifier k +initSymbol k isAbstractClass k isAbstractFunction k isArithmetic k isAssociativeArray k +isCopyable k isDeprecated k isDisabled k isFinalClass k @@ -32,10 +41,12 @@ isFloating k isFuture k isIntegral k isLazy k +isModule k isNested k isOut k isOverrideFunction k isPOD k +isPackage k isRef k isReturnOnStack k isSame k @@ -47,4 +58,6 @@ isUnsigned k isVirtualFunction k isVirtualMethod k isZeroInit k +parameters k parent k +toType k