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 local clone.

Properties

Every type and expression has properties that can be queried:

Property Examples
ExpressionValue
int.sizeofyields 4
float.nanyields the floating point nan (Not A Number) value
(float).nanyields the floating point nan value
(3).sizeofyields 4 (because 3 is an int)
int.initdefault initializer for int's
int.mangleofyields the string "i"
int.stringofyields the string "int"
(1+2).stringofyields the string "1 + 2"

Properties for All Types
PropertyDescription
.initinitializer
.sizeofsize in bytes (equivalent to C's sizeof(type))
.alignofalignment size
.mangleofstring representing the ‘mangled’ representation of the type
.stringofstring representing the source representation of the type

Properties for Integral Types
PropertyDescription
.initinitializer (0)
.maxmaximum value
.minminimum value

Properties for Floating Point Types
PropertyDescription
.initinitializer (NaN)
.infinityinfinity value
.nanNaN value
.dignumber of decimal digits of precision
.epsilonsmallest increment to the value 1
.mant_dignumber of bits in mantissa
.max_10_expmaximum int value such that 10max_10_exp is representable
.max_expmaximum int value such that 2max_exp-1 is representable
.min_10_expminimum int value such that 10min_10_exp is representable as a normalized value
.min_expminimum int value such that 2min_exp-1 is representable as a normalized value
.maxlargest representable value that's not infinity
.min_normalsmallest representable normalized value that's not 0
.rereal part
.imimaginary part

Properties for Class Types
PropertyDescription
.classinfoInformation about the dynamic type of the class

.init Property

.init produces a constant expression that is the default initializer. If applied to a type, it is the default initializer for that type. If applied to a variable or field, it is the default initializer for that variable or field's type. For example:

int a;
int b = 1;
typedef int t = 2;
t c;
t d = cast(t)3;

int.init // is 0
a.init   // is 0
b.init   // is 0
t.init   // is 2
c.init   // is 2
d.init   // is 2

struct Foo
{
    int a;
    int b = 7;
}

Foo.init.a  // is 0
Foo.init.b  // is 7

Note: .init produces a default initialized object, not default constructed. That means using .init is sometimes incorrect.

  1. If T is a nested struct, the context pointer in T.init is null.
  2. void main()
    {
        int a;
        struct S
        {
            void foo() { a = 1; }  // access a variable in enclosing scope
        }
        S s1;           // OK. S() correctly initialize its frame pointer.
        S s2 = S();     // OK. same as s1
        S s3 = S.init;  // Bad. the frame pointer in s3 is null
        s3.foo();       // Access violation
    }
    
  3. If T is a struct which has @disable this();, T.init might return a logically incorrect object.
  4. struct S
    {
        int a;
        @disable this();
        this(int n) { a = n; }
        invariant { assert(a > 0); }
        void check() {}
    }
    void main()
    {
      //S s1;           // Error: variable s1 initializer required for type S
      //S s2 = S();     // Error: constructor S.this is not callable
                        // because it is annotated with @disable
        S s3 = S.init;  // Bad. s3.a == 0, and it violates the invariant of S.
        s3.check();     // Assertion failure.
    }
    

.stringof Property

.stringof produces a constant string that is the source representation of its prefix. If applied to a type, it is the string for that type. If applied to an expression, it is the source representation of that expression. Semantic analysis is not done for that expression. For example:

module test;
import std.stdio;

struct Foo { }

enum Enum { RED }

typedef int myint;

void main()
{
    writeln((1+2).stringof);       // "1 + 2"
    writeln(Foo.stringof);         // "Foo"
    writeln(test.Foo.stringof);    // "Foo"
    writeln(int.stringof);         // "int"
    writeln((int*[5][]).stringof); // "int*[5u][]"
    writeln(Enum.RED.stringof);    // "cast(enum)0"
    writeln(test.myint.stringof);  // "myint"
    writeln((5).stringof);         // "5"
}

Note: Using .stringof for code generation is not recommended, as the internal representation of a type or expression can change between different compiler versions.

Instead you should prefer to use the identifier trait, or one of the Phobos helper functions such as fullyQualifiedName.

.sizeof Property

e.sizeof gives the size in bytes of the expression e.

When getting the size of a member, it is not necessary for there to be a this object:

struct S
{
    int a;
    static int foo()
    {
        return a.sizeof; // returns 4
    }
}

void test()
{
    int x = S.a.sizeof; // sets x to 4
}

.sizeof applied to a class object returns the size of the class reference, not the class instantiation.

.alignof Property

.alignof gives the aligned size of an expression or type. For example, an aligned size of 1 means that it is aligned on a byte boundary, 4 means it is aligned on a 32 bit boundary.

.classinfo Property

.classinfo provides information about the dynamic type of a class object. It returns a reference to type object.TypeInfo_Class.

.classinfo applied to an interface gives the information for the interface, not the class it might be an instance of.

User Defined Properties

Properties are functions that can be syntactically treated as if they were fields or variables. Properties can be read from or written to. A property is read by calling a method or function with no arguments; a property is written by calling a method or function with its argument being the value it is set to.

A simple property would be:

struct Foo
{
    @property int data() { return m_data; } // read property

    @property int data(int value) { return m_data = value; } // write property

  private:
    int m_data;
}

Properties are marked with the @property attribute. Properties may only have zero or one parameter, and may not be variadic. Property functions may not be overloaded with non-property functions.

To use it:

int test()
{
    Foo f;

    f.data = 3;        // same as f.data(3);
    return f.data + 3; // same as return f.data() + 3;
}

The absence of a read method means that the property is write-only. The absence of a write method means that the property is read-only. Multiple write methods can exist; the correct one is selected using the usual function overloading rules.

In all the other respects, these methods are like any other methods. They can be static, have different linkages, have their address taken, etc.

Note: A property can be the left-hand side of an op=, ++, or -- operator if it returns a ref.

The built in properties .sizeof, .alignof, and .mangleof may not be declared as fields or methods in structs, unions, classes or enums.

If a .property is applied to a user-defined property, the .property is applied to the result of the function call.

void main()
{
    @property int[] delegate() bar1 = { return [1, 2]; };
    auto x1 = bar1.ptr; // points to array data

    struct Foo { int* ptr; }
    @property Foo delegate() bar2 = { return Foo(); };
    auto x2 = bar2.ptr; // gets value of Foo.ptr
}