Ddoc $(SPEC_S Declarations, $(GRAMMAR $(I Declaration): $(B typedef) $(I Decl) $(B alias) $(I Decl) $(I Decl) $(I Decl): $(I StorageClasses) $(I Decl) $(I BasicType) $(I Declarators) $(B ;) $(I BasicType) $(I Declarator) $(I FunctionBody) $(GLINK AutoDeclaration) $(I Declarators): $(I DeclaratorInitializer) $(I DeclaratorInitializer) $(B ,) $(I DeclaratorIdentifierList) $(I DeclaratorInitializer): $(I Declarator) $(I Declarator) $(B =) $(I Initializer) $(I DeclaratorIdentifierList): $(I DeclaratorIdentifier) $(I DeclaratorIdentifier) $(B ,) $(I DeclaratorIdentifierList) $(I DeclaratorIdentifier): $(I Identifier) $(I Identifier) $(B =) $(I Initializer) $(I BasicType): $(B bool) $(B byte) $(B ubyte) $(B short) $(B ushort) $(B int) $(B uint) $(B long) $(B ulong) $(B char) $(B wchar) $(B dchar) $(B float) $(B double) $(B real) $(B ifloat) $(B idouble) $(B ireal) $(B cfloat) $(B cdouble) $(B creal) $(B void) $(B .)$(I IdentifierList) $(I IdentifierList) $(GLINK Typeof) $(GLINK Typeof) $(B .) $(I IdentifierList) $(I BasicType2): $(B *) $(B [ ]) $(B [) $(I Expression) $(B ]) $(B [) $(I Type) $(B ]) $(B delegate) $(I Parameters) $(B function) $(I Parameters) $(I Declarator): $(I BasicType2) $(I Declarator) $(I Identifier) $(B () $(I Declarator) $(B )) $(I Identifier) $(I DeclaratorSuffixes) $(B () $(I Declarator) $(B )) $(I DeclaratorSuffixes) $(I DeclaratorSuffixes): $(I DeclaratorSuffix) $(I DeclaratorSuffix) $(I DeclaratorSuffixes) $(I DeclaratorSuffix): $(B [ ]) $(B [) $(I Expression) $(B ]) $(B [) $(I Type) $(B ]) $(I Parameters) $(I IdentifierList): $(I Identifier) $(I Identifier) $(B .) $(I IdentifierList) $(I TemplateInstance) $(I TemplateInstance) $(B .) $(I IdentifierList) $(I StorageClasses): $(I StorageClass) $(I StorageClass) $(I StorageClasses) $(I StorageClass): $(B abstract) $(B auto) $(B const) $(B deprecated) $(B extern) $(B final) $(B invariant) $(B override) $(B scope) $(B static) $(B synchronized) $(I Type): $(I BasicType) $(I BasicType) $(I Declarator2) $(I Declarator2): $(I BasicType2) $(I Declarator2) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(I DeclaratorSuffixes) $(I Parameters): $(B $(LPAREN)) $(I ParameterList) $(B $(RPAREN)) $(B ( )) $(I ParameterList): $(I Parameter) $(I Parameter) $(B ,) $(I ParameterList) $(I Parameter) $(B ...) $(B ...) $(I Parameter): $(I Declarator) $(I Declarator) = $(ASSIGNEXPRESSION) $(I InOut) $(I Declarator) $(I InOut) $(I Declarator) = $(ASSIGNEXPRESSION) $(I InOut): $(B in) $(B out) $(B ref) $(B lazy) $(I Initializer): $(GLINK VoidInitializer) $(I NonVoidInitializer) $(I NonVoidInitializer): $(ASSIGNEXPRESSION) $(I ArrayInitializer) $(I StructInitializer) $(I ArrayInitializer): $(B [ ]) $(B [) $(I ArrayMemberInitializations) $(B ]) $(I ArrayMemberInitializations): $(I ArrayMemberInitialization) $(I ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitializations) $(I ArrayMemberInitialization): $(I NonVoidInitializer) $(ASSIGNEXPRESSION) $(B :) $(I NonVoidInitializer) $(I StructInitializer): $(B { }) $(B {) $(I StructMemberInitializers) $(B }) $(I StructMemberInitializers): $(I StructMemberInitializer) $(I StructMemberInitializer) $(B ,) $(I StructMemberInitializer) $(B ,) $(I StructMemberInitializers) $(I StructMemberInitializer): $(I NonVoidInitializer) $(I Identifier) $(B :) $(I NonVoidInitializer) )

Declaration Syntax

$(P 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 -------------------- $(P 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 -------------------- $(P Pointers to functions are declared using the $(B function) keyword: ) -------------------- int $(B function)(char) x; // x is a pointer to a function taking a char argument // and returning an int int $(B function)(char)[] x; // x is an array of pointers to functions // taking a char argument and returning an int -------------------- $(P C-style array declarations may be used as an alternative: ) -------------------- 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 -------------------- $(P 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

$(GRAMMAR $(I AutoDeclaration): $(I StorageClasses) $(I Identifier) $(B =) $(ASSIGNEXPRESSION) $(B ;) ) $(P If a declaration starts with a $(I StorageClass) and has a $(I 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 char[6] class C { ... } auto c = new C(); // c is a handle to an instance of class C ---------- The $(I 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.

Type Defining

$(P Strong types can be introduced with the typedef. Strong types are semantically a distinct type to the type checking system, for function overloading, and for the debugger. ) -------------------- typedef int myint; void foo(int x) { . } void foo(myint m) { . } . myint b; foo(b); // calls foo(myint) -------------------- Typedefs can specify a default initializer different from the default initializer of the underlying type: -------------------- typedef int myint = 7; myint m; // initialized to 7 --------------------

Type Aliasing

$(P 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: ) -------------------- $(B alias) abc.Foo.bar myint; -------------------- $(P 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: ) -------------------- $(B alias) int myint; void foo(int x) { . } void foo(myint m) { . } // error, multiply defined function foo -------------------- $(P Type aliases are equivalent to the C typedef. )

Alias Declarations

$(P A symbol can be declared as an $(I alias) of another symbol. For example: ) -------------------- import string; $(B alias) string.strlen mylen; ... int len = mylen("hello"); // actually calls string.strlen() -------------------- $(P The following alias declarations are valid: ) -------------------- template Foo2(T) { $(B alias) T t; } $(B alias) Foo2!(int) t1; $(B alias) Foo2!(int).t t2; $(B alias) t1.t t3; $(B 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 -------------------- $(P 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) { $(B alias) win32.foo myfoo; } version (linux) { $(B alias) linux.bar myfoo; } -------------------- $(P Aliasing can be used to 'import' a symbol from an import into the current scope: ) -------------------- $(B alias) string.strlen strlen; -------------------- $(P 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; } $(B 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 } -------------------- $(P $(B Note:) Type aliases can sometimes look indistinguishable from alias declarations: ) -------------------- $(B alias) foo.bar abc; // is it a type or a symbol? -------------------- $(P The distinction is made in the semantic analysis pass. ) $(P 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 $(B 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

$(GRAMMAR $(GNAME Typeof): $(B typeof $(LPAREN)) $(I Expression) $(B $(RPAREN)) $(B typeof $(LPAREN)) $(B return) $(B $(RPAREN)) ) $(P $(I Typeof) is a way to specify a type based on the type of an expression. For example: ) -------------------- void func(int i) { $(B typeof)(i) j; // j is of type int $(B typeof)(3 + 6.0) x; // x is of type double $(B typeof)(1)* p; // p is of type pointer to int int[$(B typeof)(p)] a; // a is of type int[int*] writefln("%d", $(B typeof)('c').sizeof); // prints 1 double c = cast($(B typeof)(1.0))j; // cast j to double } -------------------- $(P $(I Expression) is not evaluated, just the type of it is generated: ) -------------------- void func() { int i = 1; $(B typeof)(++i) j; // j is declared to be an int, i is not incremented writefln("%d", i); // prints 1 } -------------------- $(P There are $(V1 two) $(V2 three) special cases: $(OL $(LI $(B typeof(this)) will generate the type of what $(B this) would be in a non-static member function, even if not in a member function. ) $(LI Analogously, $(B typeof(super)) will generate the type of what $(B super) would be in a non-static member function. ) $(V2 $(LI $(B typeof(return)) will, when inside a function scope, give the return type of that function. ) ) ) ) -------------------- class A { } class B : A { $(B typeof(this)) x; // x is declared to be a B $(B typeof(super)) y; // y is declared to be an A } struct C { $(B typeof(this)) z; // z is declared to be a C* $(B typeof(super)) q; // error, no super struct for C } $(B typeof(this)) r; // error, no enclosing struct or class -------------------- $(P Where $(I Typeof) is most useful is in writing generic template code. )

Void Initializations

$(GRAMMAR $(GNAME VoidInitializer): $(B void) ) Normally, variables are initialized either with an explicit $(I Initializer) or are set to the default value for the type of the variable. If the $(I Initializer) is $(B 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 $(B void) initializers as a last resort when optimizing critical code. ) Macros: TITLE=Declarations WIKI=Declaration GLINK=$(LINK2 #$0, $(I $0)) GNAME=$(LNAME2 $0, $0) FOO=