$(DDOC $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE ) $(SPEC_S Types, $(DDOC_BLANKLINE ) $(HEADERNAV_TOC $(HEADERNAV_ITEM grammar, Grammar) $(HEADERNAV_ITEM basic-data-types, Basic Data Types) $(HEADERNAV_SUBITEMS derived-data-types, Derived Data Types, $(HEADERNAV_ITEM pointers, Pointers) ) $(HEADERNAV_ITEM user-defined-types, User-Defined Types) $(HEADERNAV_SUBITEMS type-conversions, Type Conversions, $(HEADERNAV_ITEM pointer-conversions, Pointer Conversions) $(HEADERNAV_ITEM implicit-conversions, Implicit Conversions) $(HEADERNAV_ITEM integer-promotions, Integer Promotions) $(HEADERNAV_ITEM usual-arithmetic-conversions, Usual Arithmetic Conversions) $(HEADERNAV_ITEM disallowed-conversions, Preserving Bit Patterns) $(HEADERNAV_ITEM vrp, Value Range Propagation) ) $(HEADERNAV_ITEM bool, $(D bool)) $(HEADERNAV_SUBITEMS functions, Function Types, $(HEADERNAV_ITEM delegates, Delegates) ) $(HEADERNAV_ITEM typeof, $(D typeof)) $(HEADERNAV_ITEM mixin_types, Mixin Types) $(HEADERNAV_SUBITEMS aliased-types, Aliased Types, $(HEADERNAV_ITEM size_t, $(D size_t)) $(HEADERNAV_ITEM ptrdiff_t, $(D ptrdiff_t)) $(HEADERNAV_ITEM string, $(D string)) $(HEADERNAV_ITEM noreturn, $(D noreturn)) ) ) $(DDOC_BLANKLINE )

$(LNAME2 grammar, Grammar)

$(DDOC_BLANKLINE ) $(P D is statically typed. Every expression has a type. Types constrain the values an expression can hold, and determine the semantics of operations on those values. ) $(DDOC_BLANKLINE ) $(GRAMMAR $(GNAME Type): $(GLINK TypeCtors)$(OPT ) $(GLINK BasicType) $(GLINK TypeSuffixes)$(OPT ) $(DDOC_BLANKLINE ) $(GNAME TypeCtors): $(GLINK TypeCtor) $(GLINK TypeCtor) $(GSELF TypeCtors) $(DDOC_BLANKLINE ) $(GNAME TypeCtor): $(D const) $(D immutable) $(D inout) $(D shared) $(DDOC_BLANKLINE ) $(GNAME BasicType): $(GLINK FundamentalType) $(D .) $(GLINK QualifiedIdentifier) $(GLINK QualifiedIdentifier) $(GLINK Typeof) $(GLINK Typeof) $(D .) $(GLINK QualifiedIdentifier) $(GLINK TypeCtor) $(D $(LPAREN)) $(GLINK Type) $(D $(RPAREN )) $(GLINK Vector) $(GLINK2 traits, TraitsExpression) $(GLINK MixinType) $(DDOC_BLANKLINE ) $(GNAME Vector): $(D __vector) $(D $(LPAREN)) $(GLINK VectorBaseType) $(D $(RPAREN )) $(DDOC_BLANKLINE ) $(GNAME VectorBaseType): $(GLINK Type) $(DDOC_BLANKLINE ) $(GNAME FundamentalType): $(MULTICOLS 5, $(D bool) $(D byte) $(D ubyte) $(D short) $(D ushort) $(D int) $(D uint) $(D long) $(D ulong) $(D cent) $(D ucent) $(D char) $(D wchar) $(D dchar) $(D float) $(D double) $(D real) $(D ifloat) $(D idouble) $(D ireal) $(D cfloat) $(D cdouble) $(D creal) $(D void)) $(DDOC_BLANKLINE ) $(GNAME TypeSuffixes): $(GLINK TypeSuffix) $(GSELF TypeSuffixes)$(OPT ) $(DDOC_BLANKLINE ) $(GNAME TypeSuffix): $(D *) $(D [ ]) $(D [) $(GLINK2 expression, AssignExpression) $(D ]) $(D [) $(GLINK2 expression, AssignExpression) $(D ..) $(GLINK2 expression, AssignExpression) $(D ]) $(D [) $(GLINK Type) $(D ]) $(D delegate) $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT ) $(D function) $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT ) $(DDOC_BLANKLINE ) $(GNAME QualifiedIdentifier): $(GLINK_LEX Identifier) $(GLINK_LEX Identifier) $(D .) $(GSELF QualifiedIdentifier) $(GLINK2 template, TemplateInstance) $(GLINK2 template, TemplateInstance) $(D .) $(GSELF QualifiedIdentifier) $(GLINK_LEX Identifier) $(D [) $(GLINK2 expression, AssignExpression) $(D ]) $(GLINK_LEX Identifier) $(D [) $(GLINK2 expression, AssignExpression) $(D ] .) $(GSELF QualifiedIdentifier) ) $(UL $(LI $(RELATIVE_LINK2 basic-data-types, Basic Data Types) are leaf types.) $(LI $(RELATIVE_LINK2 derived-data-types, Derived Data Types) build on leaf types.) $(LI $(RELATIVE_LINK2 user-defined-types, User-Defined Types) are aggregates of basic and derived types. ) )

$(LEGACY_LNAME2 Basic Data Types, basic-data-types, Basic Data Types)

$(DDOC_BLANKLINE ) $(TABLE_3COLS Basic Data Types, Keyword, Default Initializer ($(D .init)), Description $(TROW $(D void), no default initializer, void has no value) $(TROW $(RELATIVE_LINK2 bool, $(D bool)), $(D false), boolean value) $(TROW $(D byte), $(D 0), signed 8 bits) $(TROW $(D ubyte), $(D 0u), unsigned 8 bits) $(TROW $(D short), $(D 0), signed 16 bits) $(TROW $(D ushort), $(D 0u), unsigned 16 bits) $(TROW $(D int), $(D 0), signed 32 bits) $(TROW $(D uint), $(D 0u), unsigned 32 bits) $(TROW $(D long), $(D 0L), signed 64 bits) $(TROW $(D ulong), $(D 0uL), unsigned 64 bits) $(TROW $(D cent), $(D 0), signed 128 bits) $(TROW $(D ucent), $(D 0u), unsigned 128 bits) $(TROW $(D float), $(D float.nan), 32 bit floating point) $(TROW $(D double), $(D double.nan), 64 bit floating point) $(TROW $(D real), $(D real.nan), largest floating point size available) $(TROW $(D ifloat), $(D float.nan*1.0i), imaginary float) $(TROW $(D idouble), $(D double.nan*1.0i), imaginary double) $(TROW $(D ireal), $(D real.nan*1.0i), imaginary real) $(TROW $(D cfloat), $(D float.nan+float.nan*1.0i), a complex number of two float values) $(TROW $(D cdouble), $(D double.nan+double.nan*1.0i), complex double) $(TROW $(D creal), $(D real.nan+real.nan*1.0i), complex real) $(TROW $(D char), $(D '\xFF'), unsigned 8 bit (UTF-8 code unit)) $(TROW $(D wchar), $(D '\uFFFF'), unsigned 16 bit (UTF-16 code unit)) $(TROW $(D dchar), $(D '\U0000FFFF'), unsigned 32 bit (UTF-32 code unit)) ) $(DDOC_BLANKLINE ) $(P Endianness of basic types is part of the $(DDSUBLINK spec/abi, endianness, ABI)) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED The real floating point type has at least the range and precision of the double type. On x86 CPUs it is often implemented as the 80 bit Extended Real type supported by the x86 FPU. ) $(DDOC_BLANKLINE ) $(P NOTE: Complex and imaginary types ifloat, idouble, ireal, cfloat, cdouble, and creal have been deprecated in favor of std.complex.Complex.) $(DDOC_BLANKLINE )

$(LEGACY_LNAME2 Derived Data Types, derived-data-types, Derived Data Types)

$(DDOC_BLANKLINE ) $(UL $(LI Pointers) $(LI $(DDSUBLINK spec/arrays, static-arrays, Static Arrays)) $(LI $(DDSUBLINK spec/arrays, dynamic-arrays, Dynamic Arrays)) $(LI $(DDLINK spec/hash-map, Associative Array, Associative Arrays)) $(LI $(RELATIVE_LINK2 functions, Function Types)) $(LI $(RELATIVE_LINK2 delegates, Delegate Types)) ) $(DDOC_BLANKLINE )

$(LNAME2 pointers, Pointers)

$(DDOC_BLANKLINE ) $(P A pointer to type $(D T) has a value which is a reference (address) to another object of type $(D T). It is commonly called a $(I pointer to T) and its type is T*. To access the object value, use the * dereference operator: ) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_RUN $(D_CODE $(D_KEYWORD int)* p; $(D_KEYWORD assert)(p == $(D_KEYWORD null)); p = $(D_KEYWORD new) $(D_KEYWORD int)(5); $(D_KEYWORD assert)(p != $(D_KEYWORD null)); $(D_KEYWORD assert)(*p == 5); (*p)++; $(D_KEYWORD assert)(*p == 6); ) ) $(DDOC_BLANKLINE ) $(P If a pointer contains a $(I null) value, it is not pointing to a valid object.) $(DDOC_BLANKLINE ) $(P When a pointer to $(I T) is dereferenced, it must either contain a $(I null) value, or point to a valid object of type $(I T).) $(DDOC_BLANKLINE ) $(IMPLEMENTATION_DEFINED $(OL $(LI The behavior when a $(I null) pointer is dereferenced. Typically the program will be aborted.) )) $(DDOC_BLANKLINE ) $(UNDEFINED_BEHAVIOR dereferencing a pointer that is not $(I null) and does not point to a valid object of type $(I T).) $(DDOC_BLANKLINE ) $(P To set a pointer to point at an existing object, use the & address of operator:) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_RUN $(D_CODE $(D_KEYWORD int) i = 2; $(D_KEYWORD int)* p = &i; $(D_KEYWORD assert)(p == &i); $(D_KEYWORD assert)(*p == 2); *p = 4; $(D_KEYWORD assert)(i == 4); ) ) $(P See also $(DDSUBLINK spec/expression, pointer_arithmetic, Pointer Arithmetic).) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LEGACY_LNAME2 User Defined Types, user-defined-types, User-Defined Types)

$(DDOC_BLANKLINE ) $(UL $(LI $(DDLINK spec/enum, Enums, Enums)) $(LI $(DDLINK spec/struct, Structs and Unions, Structs and Unions)) $(LI $(DDLINK spec/class, Classes, Classes)) $(LI $(DDLINK spec/interface, Interfaces, Interfaces)) ) $(DDOC_BLANKLINE )

$(LNAME2 type-conversions, Type Conversions)

$(DDOC_BLANKLINE ) See also: $(GLINK2 expression, CastExpression). $(DDOC_BLANKLINE )

$(LEGACY_LNAME2 Pointer Conversions, pointer-conversions, Pointer Conversions)

$(DDOC_BLANKLINE ) $(P $(RELATIVE_LINK2 pointers, Pointers) implicitly convert to void*.) $(DDOC_BLANKLINE ) $(P Casting between pointers and non-pointers is allowed. Some pointer casts are disallowed in $(DDLINK spec/memory-safe-d, Memory-Safe-D-Spec, @safe code).) $(DDOC_BLANKLINE ) $(BEST_PRACTICE do not cast any pointer to a non-pointer type that points to data allocated by the garbage collector. ) $(DDOC_BLANKLINE )

$(LEGACY_LNAME2 Implicit Conversions, implicit-conversions, Implicit Conversions)

$(DDOC_BLANKLINE ) $(P Implicit conversions are used to automatically convert types as required. The rules for integers are detailed in the next sections. ) $(DDOC_BLANKLINE ) $(P An enum can be $(DDSUBLINK spec/enum, named_enums, implicitly converted) to its base type, but going the other way requires an explicit conversion.) $(DDOC_BLANKLINE ) $(UL $(LI All types implicitly convert to $(RELATIVE_LINK2 noreturn, noreturn).) $(LI Static and dynamic arrays implicitly convert to $(DDSUBLINK spec/arrays, void_arrays, void[]).) $(LI $(DDSUBLINK spec/function, function-pointers-delegates, Function pointers and delegates) can convert to covariant types.) ) $(DDOC_BLANKLINE )

$(LNAME2 class-conversions, Class Conversions)

$(DDOC_BLANKLINE ) $(P A derived class can be implicitly converted to its base class, but going the other way requires an explicit cast. For example:) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_RUN $(D_CODE $(D_KEYWORD class) Base {} $(D_KEYWORD class) Derived : Base {} Base bd = $(D_KEYWORD new) Derived(); $(D_COMMENT // implicit conversion )Derived db = $(D_KEYWORD cast)(Derived)$(D_KEYWORD new) Base(); $(D_COMMENT // explicit conversion )) ) $(DDOC_BLANKLINE ) $(P A dynamic array, say x, of a derived class can be implicitly converted to a dynamic array, say y, of a base class iff elements of x and y are qualified as being either both const or both immutable.) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_RUN $(D_CODE $(D_KEYWORD class) Base {} $(D_KEYWORD class) Derived : Base {} $(D_KEYWORD const)(Base)[] ca = ($(D_KEYWORD const)(Derived)[]).init; $(D_COMMENT // `const` elements )$(D_KEYWORD immutable)(Base)[] ia = ($(D_KEYWORD immutable)(Derived)[]).init; $(D_COMMENT // `immutable` elements )) ) $(DDOC_BLANKLINE ) $(P A static array, say x, of a derived class can be implicitly converted to a static array, say y, of a base class iff elements of x and y are qualified as being either both const or both immutable or both mutable (neither const nor immutable).) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_RUN $(D_CODE $(D_KEYWORD class) Base {} $(D_KEYWORD class) Derived : Base {} Base[3] ma = (Derived[3]).init; $(D_COMMENT // mutable elements )$(D_KEYWORD const)(Base)[3] ca = ($(D_KEYWORD const)(Derived)[3]).init; $(D_COMMENT // `const` elements )$(D_KEYWORD immutable)(Base)[3] ia = ($(D_KEYWORD immutable)(Derived)[3]).init; $(D_COMMENT // `immutable` elements )) ) $(DDOC_BLANKLINE )

$(LEGACY_LNAME2 Integer Promotions, integer-promotions, Integer Promotions)

$(DDOC_BLANKLINE ) $(P Integer Promotions are conversions of the following types: ) $(DDOC_BLANKLINE ) $(TABLE2 Integer Promotions, from, to $(TROW $(ARGS $(D bool)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D byte)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D ubyte)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D short)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D ushort)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D char)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D wchar)), $(ARGS $(D int)) ) $(TROW $(ARGS $(D dchar)), $(ARGS $(D uint)) ) ) $(DDOC_BLANKLINE ) $(P If an enum has as a base type one of the types in the left column, it is converted to the type in the right column. ) $(DDOC_BLANKLINE ) $(P Integer promotion applies to each operand of a binary expression:) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD void) fun() { $(D_KEYWORD byte) a; $(D_KEYWORD auto) b = a + a; $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(b) == $(D_KEYWORD int))); $(D_COMMENT // error: can't implicitly convert expression of type int to byte: ) $(D_COMMENT //byte c = a + a; ) $(D_KEYWORD ushort) d; $(D_COMMENT // error: can't implicitly convert expression of type int to ushort: ) $(D_COMMENT //d = d * d; ) $(D_KEYWORD int) e = d * d; $(D_COMMENT // OK ) $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)($(D_KEYWORD int)() * d) == $(D_KEYWORD int))); $(D_KEYWORD dchar) f; $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(f - f) == $(D_KEYWORD uint))); } ) ) $(DDOC_BLANKLINE ) $(RATIONALE $(UL $(LI 32-bit integer operations are often faster than smaller integer types for single variables on modern architectures.) $(LI Promotion helps avoid accidental overflow which is more common with small integer types.) ) ) $(DDOC_BLANKLINE )

$(LEGACY_LNAME2 Usual Arithmetic Conversions, usual-arithmetic-conversions, Usual Arithmetic Conversions)

$(DDOC_BLANKLINE ) $(P The usual arithmetic conversions convert operands of binary operators to a common type. The operands must already be of arithmetic types. The following rules are applied in order, looking at the base type: ) $(DDOC_BLANKLINE ) $(OL $(LI If either operand is real, the other operand is converted to real.) $(DDOC_BLANKLINE ) $(LI Else if either operand is double, the other operand is converted to double.) $(DDOC_BLANKLINE ) $(LI Else if either operand is float, the other operand is converted to float.) $(DDOC_BLANKLINE ) $(LI Else the integer promotions above are done on each operand, followed by: $(DDOC_BLANKLINE ) $(OL $(LI If both are the same type, no more conversions are done.) $(DDOC_BLANKLINE ) $(LI If both are signed or both are unsigned, the smaller type is converted to the larger.) $(DDOC_BLANKLINE ) $(LI If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type.) $(DDOC_BLANKLINE ) $(LI The signed type is converted to the unsigned type.) ) ) ) $(DDOC_BLANKLINE ) $(RATIONALE The above rules follow C99, which makes porting code from C easier.) $(DDOC_BLANKLINE ) $(P $(B Example:) Signed and unsigned conversions:) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD int) i; $(D_KEYWORD uint) u; $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(i + u) == $(D_KEYWORD uint))); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)($(D_KEYWORD short)() + u) == $(D_KEYWORD uint))); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)($(D_KEYWORD ulong)() + i) == $(D_KEYWORD ulong))); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)($(D_KEYWORD long)() - u) == $(D_KEYWORD long))); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)($(D_KEYWORD long)() * $(D_KEYWORD ulong)()) == $(D_KEYWORD ulong))); ) ) $(DDOC_BLANKLINE ) $(P $(B Example:) Floating point:) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD float) f; $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(f + $(D_KEYWORD ulong)()) == $(D_KEYWORD float))); $(D_KEYWORD double) d; $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(f * d) == $(D_KEYWORD double))); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)($(D_KEYWORD real)() / d) == $(D_KEYWORD real))); ) ) $(DDOC_BLANKLINE )

$(LNAME2 enum-ops, Enum Operations)

$(DDOC_BLANKLINE ) $(P If one or both of the operand types is an $(DDLINK spec/enum, Enums, enum) after undergoing the above conversions, the result type is determined as follows:) $(DDOC_BLANKLINE ) $(OL $(LI If the operands are the same type, the result will be of that type.) $(LI If one operand is an enum and the other is the base type of that enum, the result is the base type.) $(LI If the two operands are different enums, the result is the closest base type common to both. A base type being closer means there is a shorter sequence of conversions to base type to get there from the original type.) ) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD enum) E { a, b, c } $(D_KEYWORD enum) F { x, y } $(D_KEYWORD void) test() { E e = E.a; e = e | E.c; $(D_COMMENT //e = e + 4; // error, can't assign int to E ) $(D_KEYWORD int) i = e + 4; e += 4; $(D_COMMENT // OK, see below ) F f; $(D_COMMENT //f = e | f; // error, can't assign int to F ) i = e | f; } ) ) $(DDOC_BLANKLINE ) $(NOTE Above, e += 4 compiles because the $(DDSUBLINK spec/expression, assignment_operator_expressions, operator assignment) is equivalent to e = cast(E)(e + 4).) $(DDOC_BLANKLINE )

$(LNAME2 disallowed-conversions, Preserving Bit Patterns)

$(DDOC_BLANKLINE ) $(P Integer values cannot be implicitly converted to another type that cannot represent the integer bit pattern after integral promotion. For example:) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_FAIL $(D_CODE $(D_KEYWORD ubyte) u1 = -1; $(D_COMMENT // error, -1 cannot be represented in a ubyte )$(D_KEYWORD ushort) u2 = -1; $(D_COMMENT // error, -1 cannot be represented in a ushort )$(D_KEYWORD uint) u3 = $(D_KEYWORD int)(-1); $(D_COMMENT // ok, -1 can be represented in an int, which can be converted to a uint )$(D_KEYWORD ulong) u4 = $(D_KEYWORD long)(-1); $(D_COMMENT // ok, -1 can be represented in a long, which can be converted to a ulong )) ) $(UL $(LI Floating point types cannot be implicitly converted to integral types.) $(LI Complex or imaginary floating point types cannot be implicitly converted to non-complex floating point types.) $(LI Non-complex floating point types cannot be implicitly converted to imaginary floating point types. ) )

$(LNAME2 vrp, Value Range Propagation)

$(DDOC_BLANKLINE ) $(P Besides type-based implicit conversions, D allows certain integer expressions to implicitly convert to a narrower type after integer promotion. This works by analysing the minimum and maximum possible range of values for each expression. If that range of values matches or is a subset of a narrower target type's value range, implicit conversion is allowed. If a subexpression is known at compile-time, that can further narrow the range of values.) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD void) fun($(D_KEYWORD char) c, $(D_KEYWORD int) i, $(D_KEYWORD ubyte) b) { $(D_COMMENT // min is c.min + 100 > short.min ) $(D_COMMENT // max is c.max + 100 < short.max ) $(D_KEYWORD short) s = c + 100; $(D_COMMENT // OK ) $(D_KEYWORD ubyte) j = i & 0x3F; $(D_COMMENT // OK, 0 ... 0x3F ) $(D_COMMENT //ubyte k = i & 0x14A; // error, 0x14A > ubyte.max ) $(D_KEYWORD ushort) k = i & 0x14A; $(D_COMMENT // OK ) k = i & b; $(D_COMMENT // OK, 0 ... b.max ) $(D_COMMENT //b = b + b; // error, b.max + b.max > b.max ) s = b + b; $(D_COMMENT // OK, 0 ... b.max + b.max )} ) ) $(P Note the implementation does not track the range of possible values for mutable variables:) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD void) fun($(D_KEYWORD int) i) { $(D_KEYWORD ushort) s = i & 0xff; $(D_COMMENT // OK ) $(D_COMMENT // s is now assumed to be s.min ... s.max, not 0 ... 0xff ) $(D_COMMENT //ubyte b = s; // error ) $(D_KEYWORD ubyte) b = s & 0xff; $(D_COMMENT // OK ) $(D_KEYWORD const) $(D_KEYWORD int) c = i & 0xff; $(D_COMMENT // c's range is fixed and known ) b = c; $(D_COMMENT // OK )} ) ) $(UL $(LI For more information, see $(LINK2 https://digitalmars.com/articles/b62.html, the dmc article).) $(LI See also: $(LINK https://en.wikipedia.org/wiki/Value_range_analysis). $(DDOC_BLANKLINE ) ) )

$(LNAME2 bool, $(D bool))

$(DDOC_BLANKLINE ) $(P The bool type is a byte-size type that can only hold the value true or false.) $(DDOC_BLANKLINE ) $(P The only operators that can accept operands of type bool are: $(CODE_AMP ) $(CODE_PIPE ), $(D ^), $(CODE_AMP )$(D =), $(CODE_PIPE )$(D =), $(D ^=), !, $(CODE_AMP )$(CODE_AMP ), $(CODE_PIPE )$(CODE_PIPE ), and $(D ?:).) $(DDOC_BLANKLINE ) $(P A bool value can be implicitly converted to any integral type, with false becoming 0 and true becoming 1.) $(DDOC_BLANKLINE ) $(P The numeric literals 0 and 1 can be implicitly converted to the bool values false and true, respectively. Casting an expression to bool means testing for 0 or !=0 for arithmetic types, and null or !=null for pointers or references.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 functions, Function Types)

$(DDOC_BLANKLINE ) $(P A function type has the form:) $(DDOC_BLANKLINE ) $(GRAMMAR_INFORMATIVE $(GLINK2 declaration, StorageClasses)$(OPT ) $(GLINK Type) $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT ) ) $(DDOC_BLANKLINE ) $(P Function types are not included in the $(GLINK Type) grammar. A function type e.g. int(int) $(DDSUBLINK spec/declaration, alias-function, can be aliased). A function type is only used for type tests or as the target type of a pointer.) $(DDOC_BLANKLINE ) $(P Instantiating a function type is illegal. Instead, a pointer to function or delegate can be used. Those have these type forms respectively:) $(DDOC_BLANKLINE ) $(GRAMMAR_INFORMATIVE $(GLINK Type) function $(GLINK2 function, Parameters) $(GLINK2 function, FunctionAttributes)$(OPT ) $(GLINK Type) delegate $(GLINK2 function, Parameters) $(GLINK2 function, MemberFunctionAttributes)$(OPT ) ) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD void) f($(D_KEYWORD int)); $(D_KEYWORD alias) Fun = $(D_KEYWORD void)($(D_KEYWORD int)); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(f) == Fun)); $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)(Fun* == $(D_KEYWORD void) $(D_KEYWORD function)($(D_KEYWORD int)))); ) ) $(DDOC_BLANKLINE ) $(P See $(DDSUBLINK spec/function, function-pointers, Function Pointers).) $(DDOC_BLANKLINE )

$(LNAME2 delegates, Delegates)

$(DDOC_BLANKLINE ) $(P Delegates are an aggregate of two pieces of data, either:) $(UL $(LI An object reference and a pointer to a non-static $(DDSUBLINK spec/class, member-functions, member function).) $(LI A pointer to a closure and a pointer to a $(DDSUBLINK spec/function, nested, nested function). The object reference forms the this pointer when the function is called.) )) $(DDOC_BLANKLINE ) $(P Delegates are declared and initialized similarly to function pointers:) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE $(D_KEYWORD int) $(D_KEYWORD delegate)($(D_KEYWORD int)) dg; $(D_COMMENT // dg is a delegate to a function ) $(D_KEYWORD class) OB { $(D_KEYWORD int) member($(D_KEYWORD int)); } $(D_KEYWORD void) f(OB o) { dg = &o.member; $(D_COMMENT // dg is a delegate to object o and member function member )} ) ) $(DDOC_BLANKLINE ) $(P Delegates cannot be initialized with static member functions or non-member functions. ) $(DDOC_BLANKLINE ) $(P Delegates are called analogously to function pointers: ) $(DDOC_BLANKLINE ) $(D_CODE fp(3); $(D_COMMENT // call func$(LPAREN)3$(RPAREN ) )dg(3); $(D_COMMENT // call o.member$(LPAREN)3$(RPAREN ) )) $(DDOC_BLANKLINE ) $(P The equivalent of member function pointers can be constructed using $(DDSUBLINK spec/expression, function_literals, anonymous lambda functions):) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_RUN $(D_CODE $(D_KEYWORD class) C { $(D_KEYWORD int) a; $(D_KEYWORD int) foo($(D_KEYWORD int) i) { $(D_KEYWORD return) i + a; } } $(D_COMMENT // mfp is the member function pointer )$(D_KEYWORD auto) mfp = $(D_KEYWORD function)(C self, $(D_KEYWORD int) i) { $(D_KEYWORD return) self.foo(i); }; $(D_KEYWORD auto) c = $(D_KEYWORD new) C(); $(D_COMMENT // create an instance of C )mfp(c, 1); $(D_COMMENT // and call c.foo$(LPAREN)1$(RPAREN ) )) ) $(DDOC_BLANKLINE )

$(LNAME2 typeof, $(D typeof))

$(DDOC_BLANKLINE ) $(GRAMMAR $(GNAME Typeof): $(D typeof $(LPAREN)) $(GLINK2 expression, Expression) $(D $(RPAREN )) $(D typeof $(LPAREN)) $(D return) $(D $(RPAREN )) ) $(DDOC_BLANKLINE ) $(P $(D typeof) is a way to specify a type based on the type of an expression. For example: ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD void) func($(D_KEYWORD int) i) { $(D_KEYWORD typeof)(i) j; $(D_COMMENT // j is of type int ) $(D_KEYWORD typeof)(3 + 6.0) x; $(D_COMMENT // x is of type double ) $(D_KEYWORD typeof)(1)* p; $(D_COMMENT // p is of type pointer to int ) $(D_KEYWORD int)[$(D_KEYWORD typeof)(p)] a; $(D_COMMENT // a is of type int[int*] ) writeln($(D_KEYWORD typeof)('c').sizeof); $(D_COMMENT // prints 1 ) $(D_KEYWORD double) c = $(D_KEYWORD cast)($(D_KEYWORD typeof)(1.0))j; $(D_COMMENT // cast j to double )} ) $(DDOC_BLANKLINE ) $(P $(I Expression) is not evaluated, it is used purely to generate the type: ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD void) func() { $(D_KEYWORD int) i = 1; $(D_KEYWORD typeof)(++i) j; $(D_COMMENT // j is declared to be an int, i is not incremented ) writeln(i); $(D_COMMENT // prints 1 )} ) $(DDOC_BLANKLINE ) $(P If Expression is a $(DDSUBLINK spec/template, variadic-templates, $(I ValueSeq)) it will produce a TypeSeq containing the types of each element.) $(DDOC_BLANKLINE ) $(P Special cases: ) $(OL $(LI $(D typeof(return)) will, when inside a function scope, give the return type of that function. ) $(LI $(LNAME2 typeof-this, $(D typeof(this))) will generate the type of what $(D this) would be in a non-static member function, even if not in a member function. ) $(LI Analogously, $(D typeof(super)) will generate the type of what $(D super) would be in a non-static member function. ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD class) A { } $(D_KEYWORD class) B : A { $(D_KEYWORD typeof)($(D_KEYWORD this)) x; $(D_COMMENT // x is declared to be a B ) $(D_KEYWORD typeof)($(D_KEYWORD super)) y; $(D_COMMENT // y is declared to be an A )} $(D_KEYWORD struct) C { $(D_KEYWORD static) $(D_KEYWORD typeof)($(D_KEYWORD this)) z; $(D_COMMENT // z is declared to be a C ) $(D_KEYWORD typeof)($(D_KEYWORD super)) q; $(D_COMMENT // error, no super struct for C )} $(D_KEYWORD typeof)($(D_KEYWORD this)) r; $(D_COMMENT // error, no enclosing struct or class )) ) $(DDOC_BLANKLINE ) $(P If the expression is a $(DDSUBLINK spec/function, property-functions, Property Function), $(D typeof) gives its return type. ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD struct) S { @property $(D_KEYWORD int) foo() { $(D_KEYWORD return) 1; } } $(D_KEYWORD typeof)(S.foo) n; $(D_COMMENT // n is declared to be an int )) $(DDOC_BLANKLINE ) $(P If the expression is a $(DDLINK , spec/template, Template, Template), $(D typeof) gives the type $(D void). ) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD template) t {} $(D_KEYWORD static) $(D_KEYWORD assert)($(D_KEYWORD is)($(D_KEYWORD typeof)(t) == $(D_KEYWORD void))); ) $(DDOC_BLANKLINE ) $(BEST_PRACTICE $(OL $(LI $(I Typeof) is most useful in writing generic template code.) ) ) $(DDOC_BLANKLINE )

$(LNAME2 mixin_types, Mixin Types)

$(DDOC_BLANKLINE ) $(GRAMMAR $(GNAME MixinType): $(D mixin $(LPAREN)) $(GLINK2 expression, ArgumentList) $(D $(RPAREN )) ) $(DDOC_BLANKLINE ) $(P Each $(GLINK2 expression, AssignExpression) in the $(I ArgumentList) is evaluated at compile time, and the result must be representable as a string. The resulting strings are concatenated to form a string. The text contents of the string must be compilable as a valid $(GLINK2 type, Type), and is compiled as such.) $(DDOC_BLANKLINE ) $(D_CODE $(D_KEYWORD void) test($(D_KEYWORD mixin)($(D_STRING "int"))* p) $(D_COMMENT // int* p ){ $(D_KEYWORD mixin)($(D_STRING "int"))[] a; $(D_COMMENT // int[] a; ) $(D_KEYWORD mixin)($(D_STRING "int[]")) b; $(D_COMMENT // int[] b; )} ) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE )

$(LNAME2 aliased-types, Aliased Types)

$(DDOC_BLANKLINE )

$(LNAME2 size_t, $(D size_t))

$(DDOC_BLANKLINE ) $(P $(D size_t) is an alias to one of the unsigned integral basic types, and represents a type that is large enough to represent an offset into all addressable memory.) $(DDOC_BLANKLINE )

$(LNAME2 ptrdiff_t, $(D ptrdiff_t))

$(P $(D ptrdiff_t) is an alias to the signed integral basic type the same size as $(D size_t).) $(DDOC_BLANKLINE )

$(LNAME2 string, $(D string))

$(DDOC_BLANKLINE ) $(P A $(DDSUBLINK spec/arrays, strings, $(I string) is a special case of an array.)) $(DDOC_BLANKLINE )

$(LNAME2 noreturn, $(D noreturn))

$(DDOC_BLANKLINE ) $(P noreturn is the $(LINK2 https://en.wikipedia.org/wiki/Bottom_type, bottom type) which can implicitly convert to any type, including void. A value of type noreturn will never be produced and the compiler can optimize such code accordingly.) $(DDOC_BLANKLINE ) $(P A function that $(DDSUBLINK spec/function, function-return-values, never returns) has the return type noreturn. This can occur due to an infinite loop or always throwing an exception.) $(DDOC_BLANKLINE ) $(SPEC_RUNNABLE_EXAMPLE_COMPILE $(D_CODE noreturn abort($(D_KEYWORD const)($(D_KEYWORD char))[] message); $(D_KEYWORD int) example($(D_KEYWORD int) i) { $(D_KEYWORD if) (i < 0) { $(D_COMMENT // abort does not return, so it doesn't need to produce an int ) $(D_KEYWORD int) val = abort($(D_STRING "less than zero")); } $(D_COMMENT // ternary expression's common type is still int ) $(D_KEYWORD return) i != 0 ? 1024 / i : abort($(D_STRING "calculation went awry.")); } ) ) $(DDOC_BLANKLINE ) $(P noreturn is defined as $(D typeof(*null)). This is because dereferencing a null literal halts execution.) $(DDOC_BLANKLINE ) $(DDOC_BLANKLINE ) $(SPEC_SUBNAV_PREV_NEXT declaration, Declarations, property, Properties) ) )