Types - D Programming Language

Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Calendar
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# Types

Contents

1. Basic Data Types
2. Derived Data Types
3. User-Defined Types
4. Type Conversions
   1. Pointer Conversions
   2. Implicit Conversions
   3. Integer Promotions
   4. Usual Arithmetic Conversions
5. bool
6. Delegates
7. typeof
8. Mixin Types
9. Aliased Types
   1. size_t
   2. ptrdiff_t
   3. string

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.

    Type:
        TypeCtorsopt BasicType TypeSuffixesopt

    TypeCtors:
        TypeCtor
        TypeCtor TypeCtors

    TypeCtor:
        const
        immutable
        inout
        shared

    BasicType:
        FundamentalType
        . QualifiedIdentifier
        QualifiedIdentifier
        Typeof
        Typeof . QualifiedIdentifier
        TypeCtor ( Type )
        Vector
        Traits
        MixinType

    Vector:
        __vector ( VectorBaseType )

    VectorBaseType:
        Type

    FundamentalType:
        bool
        byte
        ubyte
        short
        ushort
        int
        uint
        long
        ulong
        cent
        ucent
        char
        wchar
        dchar
        float
        double
        real
        ifloat
        idouble
        ireal
        cfloat
        cdouble
        creal
        void

    TypeSuffixes:
        TypeSuffix TypeSuffixesopt

    TypeSuffix:
        *
        [ ]
        [ AssignExpression ]
        [ AssignExpression .. AssignExpression ]
        [ Type ]
        delegate Parameters MemberFunctionAttributesopt
        function Parameters FunctionAttributesopt

    QualifiedIdentifier:
        Identifier
        Identifier . QualifiedIdentifier
        TemplateInstance
        TemplateInstance . QualifiedIdentifier
        Identifier [ AssignExpression ]
        Identifier [ AssignExpression ]. QualifiedIdentifier

Basic Data Types are leaf types. Derived Data Types build on leaf types. User-Defined Types are aggregates of basic and derived types.

## Basic Data Types

Basic Data Types
Keyword | Default Initializer (.init) | Description
--- | --- | ---
void | no default initializer | void has no value
bool | false | boolean value
byte | 0 | signed 8 bits
ubyte | 0u | unsigned 8 bits
short | 0 | signed 16 bits
ushort | 0u | unsigned 16 bits
int | 0 | signed 32 bits
uint | 0u | unsigned 32 bits
long | 0L | signed 64 bits
ulong | 0uL | unsigned 64 bits
cent | 0 | signed 128 bits (reserved for future use)
ucent | 0u | unsigned 128 bits (reserved for future use)
float | float.nan | 32 bit floating point
double | double.nan | 64 bit floating point
real | real.nan | largest floating point size available
ifloat | float.nan*1.0i | imaginary float
idouble | double.nan*1.0i | imaginary double
ireal | real.nan*1.0i | imaginary real
cfloat | float.nan+float.nan*1.0i | a complex number of two float values
cdouble | double.nan+double.nan*1.0i | complex double
creal | real.nan+real.nan*1.0i | complex real
char | 'xFF' | unsigned 8 bit (UTF-8 code unit)
wchar | 'uFFFF' | unsigned 16 bit (UTF-16 code unit)
dchar | 'U0000FFFF' | unsigned 32 bit (UTF-32 code unit)

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.

NOTE: Complex and imaginary types ifloat, idouble, ireal, cfloat, cdouble, and creal have been deprecated in favor of std.complex.Complex.

## Derived Data Types

- Pointer
- Static Array
- Dynamic Array
- Associative Array
- Functions
- Delegates

## User-Defined Types

- Enums
- Structs and Unions
- Classes
- Interfaces

## Type Conversions

See also: CastExpression.

### Pointer Conversions

Casting pointers to non-pointers and vice versa is allowed.

Best Practices: do not do this for any pointers that point to data allocated by the garbage collector.

### Implicit Conversions

Implicit conversions are used to automatically convert types as required.

An enum can be implicitly converted to its base type, but going the other way requires an explicit conversion. For example:

    int i;

    enum Foo { E }
    Foo f;
    i = f;           // OK
    f = i;           // error
    f = cast(Foo)i;  // OK
    f = 0;           // error
    f = Foo.E;       // OK

A derived class can be implicitly converted to its base class, but going the other way requires an explicit cast. For example:

    class Base {}
    class Derived : Base {}
    Base bd = new Derived();              // implicit conversion
    Derived db = cast(Derived)new Base(); // explicit conversion

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.

    class Base {}
    class Derived : Base {}
    const(Base)[] ca = (const(Derived)[]).init; // `const` elements
    immutable(Base)[] ia = (immutable(Derived)[]).init; // `immutable` elements

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).

    class Base {}
    class Derived : Base {}
    Base[3] ma = (Derived[3]).init; // mutable elements
    const(Base)[3] ca = (const(Derived)[3]).init; // `const` elements
    immutable(Base)[3] ia = (immutable(Derived)[3]).init; // `immutable` elements

### Integer Promotions

Integer Promotions are conversions of the following types:

Integer Promotions
from | to
--- | ---
bool | int
byte | int
ubyte | int
short | int
ushort | int
char | int
wchar | int
dchar | uint

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.

### Usual Arithmetic Conversions

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:

1. If either operand is real, the other operand is converted to real.
2. Else if either operand is double, the other operand is converted to double.
3. Else if either operand is float, the other operand is converted to float.
4. Else the integer promotions are done on each operand, followed by:
   1. If both are the same type, no more conversions are done.
   2. If both are signed or both are unsigned, the smaller type is converted to the larger.
   3. If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type.
   4. The signed type is converted to the unsigned type.

If one or both of the operand types is an enum after undergoing the above conversions, the result type is:

1. If the operands are the same type, the result will be of that type.
2. If one operand is an enum and the other is the base type of that enum, the result is the base type.
3. 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.

Integer values cannot be implicitly converted to another type that cannot represent the integer bit pattern after integral promotion. For example:

    ubyte  u1 = -1;       // error, -1 cannot be represented in a ubyte
    ushort u2 = -1;       // error, -1 cannot be represented in a ushort
    uint   u3 = int(-1);  // ok, -1 can be represented in a uint
    ulong  u4 = long(-1); // ok, -1 can be represented in a ulong

Floating point types cannot be implicitly converted to integral types. Complex or imaginary floating point types cannot be implicitly converted to non-complex floating point types. Non-complex floating point types cannot be implicitly converted to imaginary floating point types.

## bool

The bool type is a byte-size type that can only hold the value true or false.

The only operators that can accept operands of type bool are: & |, ^, &=, |=, ^=, !, &&, ||, and ?:.

A bool value can be implicitly converted to any integral type, with false becoming 0 and true becoming 1.

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.

## Delegates

Delegates are an aggregate of two pieces of data: an object reference and a pointer to a non-static member function, or a pointer to a closure and a pointer to a nested function. The object reference forms the this pointer when the function is called.

Delegates are declared similarly to function pointers:

    int function(int) fp; // fp is pointer to a function
    int delegate(int) dg; // dg is a delegate to a function

A delegate is initialized analogously to function pointers:

    int func(int);
    fp = &func;   // fp points to func
    class OB
    {
        int member(int);
    }
    OB o;
    dg = &o.member; // dg is a delegate to object o and
                    // member function member

Delegates cannot be initialized with static member functions or non-member functions.

Delegates are called analogously to function pointers:

    fp(3);   // call func(3)
    dg(3);   // call o.member(3)

The equivalent of member function pointers can be constructed using anonymous lambda functions:

    class C
    {
        int a;
        int foo(int i) { return i + a; }
    }

    // mfp is the member function pointer
    auto mfp = function(C self, int i) { return self.foo(i); };
    auto c = new C();  // create an instance of C
    mfp(c, 1);  // and call c.foo(1)

The C style syntax for declaring pointers to functions is deprecated:

    int (*fp)(int);  // fp is pointer to a function

## typeof

    Typeof:
        typeof ( Expression )
        typeof ( return )

typeof is a way to specify a type based on the type of an expression. For example:

    void func(int i)
    {
        typeof(i) j;       // j is of type int
        typeof(3 + 6.0) x; // x is of type double
        typeof(1)* p;      // p is of type pointer to int
        int[typeof(p)] a;  // a is of type int[int*]

        writeln(typeof('c').sizeof); // prints 1
        double c = cast(typeof(1.0))j; // cast j to double
    }

Expression is not evaluated, it is used purely to generate the type:

    void func()
    {
        int i = 1;
        typeof(++i) j; // j is declared to be an int, i is not incremented
        writeln(i);  // prints 1
    }

Special cases:

1. typeof(this) will generate the type of what this would be in a non-static member function, even if not in a member function.
2. Analogously, typeof(super) will generate the type of what super would be in a non-static member function.
3. typeof(return) will, when inside a function scope, give the return type of that function.

    class A { }

    class B : A
    {
        typeof(this) x;  // x is declared to be a B
        typeof(super) y; // y is declared to be an A
    }

    struct C
    {
        static typeof(this) z;  // z is declared to be a C

        typeof(super) q; // error, no super struct for C
    }

    typeof(this) r;   // error, no enclosing struct or class

If the expression is a Property Function, typeof gives its return type.

    struct S
    {
        @property int foo() { return 1; }
    }
    typeof(S.foo) n;  // n is declared to be an int

Best Practices:

1. Typeof is most useful in writing generic template code.

## Mixin Types

    MixinType:
        mixin ( ArgumentList )

Each AssignExpression in the 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 Type, and is compiled as such.

    void test(mixin("int")* p) // int* p
    {
        mixin("int")[] a;      // int[] a;
        mixin("int[]") b;      // int[] b;
    }

## Aliased Types

### size_t

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.

### ptrdiff_t

ptrdiff_t is an alias to the signed integral basic type the same size as size_t.

### string

A string is a special case of an array.

Declarations
Properties
Copyright © 1999-2021 by the D Language Foundation | Page generated by Ddoc on Mon Aug 2 20:26:59 2021