D Programming Language 2.0

- Forum
- Wiki
- Search
- Downloads
- Home

Last update Sun Oct 2 23:49:22 2011

# Declarations

    Declaration:
        alias Decl
        Decl

    Decl:
        StorageClasses Decl
        BasicType Declarators ;
        BasicType Declarator FunctionBody
        AutoDeclaration

    Declarators:
        DeclaratorInitializer
        DeclaratorInitializer , DeclaratorIdentifierList

    DeclaratorInitializer:
        Declarator
        Declarator = Initializer

    DeclaratorIdentifierList:
        DeclaratorIdentifier
        DeclaratorIdentifier , DeclaratorIdentifierList

    DeclaratorIdentifier:
        Identifier
        Identifier = Initializer

    BasicType:
        BasicTypeX
        .IdentifierList
        IdentifierList
        Typeof
        Typeof . IdentifierList
            const( Type )
            immutable( Type )
            shared( Type )
            inout( Type )

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

    BasicType2:
        *
        [ ]
        [ AssignExpression ]
        [ AssignExpression .. AssignExpression ]
        [ Type ]
        delegate Parameters FunctionAttributesopt
        function Parameters FunctionAttributesopt

    Declarator:
        BasicType2opt ( Declarator ) DeclaratorSuffixesopt
        BasicType2opt Identifier DeclaratorSuffixesopt

    DeclaratorSuffixes:
        DeclaratorSuffix
        DeclaratorSuffix DeclaratorSuffixes

    DeclaratorSuffix:
        [ ]
        [ AssignExpression ]
        [ Type ]
        TemplateParameterListopt Parameters MemberFunctionAttributesopt Constraintopt

    IdentifierList:
        Identifier
        Identifier . IdentifierList
        TemplateInstance
        TemplateInstance . IdentifierList

    StorageClasses:
        StorageClass
        StorageClass StorageClasses

    StorageClass:
        abstract
        auto
        const
        deprecated
        extern
        final
        immutable
        inout
        shared
        nothrow
        override
        pure
        __gshared
        Property
        scope
        static
        synchronized

    Property:
        @ Identifier

    Type:
        BasicType
        BasicType Declarator2

    Declarator2:
        BasicType2opt DeclaratorSuffixesopt
        BasicType2opt ( Declarator2 ) DeclaratorSuffixesopt

    Parameters:
        ( ParameterList )
        ( )

    ParameterList:
        Parameter
        Parameter , ParameterList
        ...

    Parameter:
        InOutopt BasicType Declarator
        InOutopt BasicType Declarator ...
        InOutopt BasicType Declarator = DefaultInitializerExpression
        InOutopt Type
        InOutopt Type ...

    InOut:
        InOutX
        InOut InOutX

    InOutX:
        auto
        const
        final
        immutable
        in
        inout
        lazy
        out
        ref
        scope
        shared

    FunctionAttributes:
        FunctionAttribute
        FunctionAttribute FunctionAttributes

    FunctionAttribute:
        nothrow
        pure
        Property

    MemberFunctionAttributes:
        MemberFunctionAttribute
        MemberFunctionAttribute MemberFunctionAttributes

    MemberFunctionAttribute:
        const
        immutable
        inout
        shared
        FunctionAttribute

    DefaultInitializerExpression:
        AssignExpression
        __FILE__
        __LINE__

    Initializer:
        VoidInitializer
        NonVoidInitializer

    NonVoidInitializer:
        AssignExpression
        ArrayInitializer
        StructInitializer

    ArrayInitializer:
        [ ]
        [ ArrayMemberInitializations ]

    ArrayMemberInitializations:
        ArrayMemberInitialization
        ArrayMemberInitialization ,
        ArrayMemberInitialization , ArrayMemberInitializations

    ArrayMemberInitialization:
        NonVoidInitializer
        AssignExpression : NonVoidInitializer

    StructInitializer:
        {  }
        { StructMemberInitializers }

    StructMemberInitializers:
        StructMemberInitializer
        StructMemberInitializer ,
        StructMemberInitializer , StructMemberInitializers

    StructMemberInitializer:
        NonVoidInitializer
        Identifier : NonVoidInitializer

### Declaration Syntax

Declaration syntax generally reads right to left:

    int x;    // x is an int
    int* x;   // x is a pointer to int
    int** x;  // x is a pointer to a pointer to int
    int[] x;  // x is an array of ints
    int*[] x; // x is an array of pointers to ints
    int[]* x; // x is a pointer to an array of ints

Arrays read right to left as well:

    int[3] x;     // x is an array of 3 ints
    int[3][5] x;  // x is an array of 5 arrays of 3 ints
    int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints

Pointers to functions are declared using the function keyword:

    int function(char) x; // x is a pointer to
                         // a function taking a char argument
                         // and returning an int
    int function(char)[] x; // x is an array of
                         // pointers to functions
                         // taking a char argument
                         // and returning an int

C-style array, function pointer and pointer to array declarations are deprecated:

    int x[3];          // x is an array of 3 ints
    int x[3][5];       // x is an array of 3 arrays of 5 ints
    int (*x[5])[3];    // x is an array of 5 pointers to arrays of 3 ints
    int (*x)(char);    // x is a pointer to a function taking a char argument
                       // and returning an int
    int (*[] x)(char); // x is an array of pointers to functions
                       // taking a char argument and returning an int

In a declaration declaring multiple symbols, all the declarations must be of the same type:

    int x,y;   // x and y are ints
    int* x,y;  // x and y are pointers to ints
    int x,*y;  // error, multiple types
    int[] x,y; // x and y are arrays of ints
    int x[],y; // error, multiple types

### Implicit Type Inference

    AutoDeclaration:
        StorageClasses AutoDeclarationX ;

    AutoDeclarationX:
        Identifier = Initializer
        AutoDeclarationX , Identifier = Initializer

If a declaration starts with a StorageClass and has a NonVoidInitializer from which the type can be inferred, the type on the declaration can be omitted.

    static x = 3;      // x is type int
    auto y = 4u;       // y is type uint
    auto s = "string"; // s is type immutable(char)[]

    class C { ... }

    auto c = new C();  // c is a handle to an instance of class C

The NonVoidInitializer cannot contain forward references (this restriction may be removed in the future). The implicitly inferred type is statically bound to the declaration at compile time, not run time.

An ArrayLiteral is inferred to be a dynamic array type rather than a static array:

    auto v = ["hello", "world"]; // type is string[], not string[2]

### Type Aliasing

It's sometimes convenient to use an alias for a type, such as a shorthand for typing out a long, complex type like a pointer to a function. In D, this is done with the alias declaration:

    alias abc.Foo.bar myint;

Aliased types are semantically identical to the types they are aliased to. The debugger cannot distinguish between them, and there is no difference as far as function overloading is concerned. For example:

    alias int myint;

    void foo(int x) { . }
    void foo(myint m) { . } // error, multiply defined function foo

### Alias Declarations

A symbol can be declared as an alias of another symbol. For example:

    import string;

    alias string.strlen mylen;
     ...
    int len = mylen("hello"); // actually calls string.strlen()

The following alias declarations are valid:

    template Foo2(T) { alias T t; }
    alias Foo2!(int) t1;
    alias Foo2!(int).t t2;
    alias t1.t t3;
    alias t2 t4;

    t1.t v1;  // v1 is type int
    t2 v2;    // v2 is type int
    t3 v3;    // v3 is type int
    t4 v4;    // v4 is type int

Aliased symbols are useful as a shorthand for a long qualified symbol name, or as a way to redirect references from one symbol to another:

    version (Win32)
    {
        alias win32.foo myfoo;
    }
    version (linux)
    {
        alias linux.bar myfoo;
    }

Aliasing can be used to ‘import’ a symbol from an import into the current scope:

    alias string.strlen strlen;

Aliases can also ‘import’ a set of overloaded functions, that can be overloaded with functions in the current scope:

    class A {
        int foo(int a) { return 1; }
    }

    class B : A {
        int foo( int a, uint b ) { return 2; }
    }

    class C : B {
        int foo( int a ) { return 3; }
        alias B.foo foo;
    }

    class D : C  {
    }

    void test()
    {
        D b = new D();
        int i;

        i = b.foo(1, 2u);   // calls B.foo
        i = b.foo(1);       // calls C.foo
    }

Note: Type aliases can sometimes look indistinguishable from alias declarations:

    alias foo.bar abc; // is it a type or a symbol?

The distinction is made in the semantic analysis pass.

Aliases cannot be used for expressions:

    struct S { static int i; }
    S s;

    alias s.i a; // illegal, s.i is an expression
    alias S.i b; // ok
    b = 4;       // sets S.i to 4

### Extern Declarations

Variable declarations with the storage class extern are not allocated storage within the module. They must be defined in some other object file with a matching name which is then linked in. The primary usefulness of this is to connect with global variable declarations in C files.

### 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*]

     writefln("%d", typeof('c').sizeof); // prints 1
     double c = cast(typeof(1.0))j; // cast j to double
    }

Expression is not evaluated, just the type of it is generated:

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

There are three 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 {
     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

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

### Void Initializations

    VoidInitializer:
        void

Normally, variables are initialized either with an explicit Initializer or are set to the default value for the type of the variable. If the Initializer is void, however, the variable is not initialized. If its value is used before it is set, undefined program behavior will result.

    void foo() {
     int x = void;
     writefln(x);  // will print garbage
    }

Therefore, one should only use void initializers as a last resort when optimizing critical code.
Forums | Comments | D | Search | Downloads | Home
Copyright © 1999-2011 by Digital Mars ®, All Rights Reserved | Page generated by Ddoc.