Ddoc
$(SPEC_S Declarations,
$(GRAMMAR
$(GNAME Declaration):
$(V1 $(B typedef) $(I Decl)
) $(B alias) $(I Decl)
$(I Decl)
$(GNAME Decl):
$(GLINK StorageClasses) $(I Decl)
$(GLINK BasicType) $(GLINK Declarators) $(B ;)
$(GLINK BasicType) $(GLINK Declarator) $(LINK2 function.html#FunctionBody, $(I FunctionBody))
$(GLINK AutoDeclaration)
$(GNAME Declarators):
$(I DeclaratorInitializer)
$(I DeclaratorInitializer) $(B ,) $(GLINK DeclaratorIdentifierList)
$(GNAME DeclaratorInitializer):
$(GLINK Declarator)
$(GLINK Declarator) $(B =) $(GLINK Initializer)
$(GNAME DeclaratorIdentifierList):
$(GLINK DeclaratorIdentifier)
$(GLINK DeclaratorIdentifier) $(B ,) $(I DeclaratorIdentifierList)
$(GNAME DeclaratorIdentifier):
$(I Identifier)
$(I Identifier) $(B =) $(GLINK Initializer)
$(GNAME BasicType):
$(GLINK BasicTypeX)
$(B .)$(GLINK IdentifierList)
$(GLINK IdentifierList)
$(GLINK Typeof)
$(GLINK Typeof) $(B .) $(GLINK IdentifierList)
$(V2 $(B const$(LPAREN)) $(GLINK type) $(B $(RPAREN))
$(B immutable$(LPAREN)) $(GLINK type) $(B $(RPAREN))
$(B shared$(LPAREN)) $(GLINK type) $(B $(RPAREN))
$(B inout$(LPAREN)) $(GLINK type) $(B $(RPAREN))
)
$(GNAME BasicTypeX):
$(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)
$(GNAME BasicType2):
$(B *)
$(B [ ])
$(B [) $(VEXPRESSION) $(B ])
$(B [) $(VEXPRESSION) .. $(VEXPRESSION) $(B ])
$(B [) $(GLINK Type) $(B ])
$(B delegate) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT))
$(B function) $(GLINK Parameters) $(V2 $(GLINK FunctionAttributes)$(OPT))
$(GNAME Declarator):
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT)
$(GLINK BasicType2)$(OPT) $(I Identifier) $(GLINK DeclaratorSuffixes)$(OPT)
$(GNAME DeclaratorSuffixes):
$(GLINK DeclaratorSuffix)
$(GLINK DeclaratorSuffix) $(I DeclaratorSuffixes)
$(GNAME DeclaratorSuffix):
$(B [ ])
$(B [) $(VEXPRESSION) $(B ])
$(B [) $(GLINK Type) $(B ])
$(GLINK2 template, TemplateParameterList)$(OPT) $(GLINK Parameters) $(V2 $(GLINK MemberFunctionAttributes)$(OPT) $(GLINK2 template, Constraint)$(OPT))
$(GNAME IdentifierList):
$(I Identifier)
$(I Identifier) $(B .) $(I IdentifierList)
$(GLINK2 template, TemplateInstance)
$(GLINK2 template, TemplateInstance) $(B .) $(I IdentifierList)
$(GNAME StorageClasses):
$(GLINK StorageClass)
$(GLINK StorageClass) $(I StorageClasses)
$(GNAME StorageClass):
$(B abstract)
$(B auto)
$(B const)
$(B deprecated)
$(B extern)
$(B final)
$(V2 $(B immutable)
$(B inout)
$(B shared)
$(B nothrow)
$(B override)
$(B pure)
$(B __gshared)
$(GLINK Property)
) $(B scope)
$(B static)
$(B synchronized)
$(GNAME Property):
$(B @) $(I Identifier)
$(GNAME Type):
$(GLINK BasicType)
$(GLINK BasicType) $(GLINK Declarator2)
$(GNAME Declarator2):
$(GLINK BasicType2)$(OPT) $(GLINK DeclaratorSuffixes)$(OPT)
$(GLINK BasicType2)$(OPT) $(B $(LPAREN)) $(I Declarator2) $(B $(RPAREN)) $(GLINK DeclaratorSuffixes)$(OPT)
$(GNAME Parameters):
$(B $(LPAREN)) $(GLINK ParameterList) $(B $(RPAREN))
$(B ( ))
$(GNAME ParameterList):
$(GLINK Parameter)
$(GLINK Parameter) $(B ,) $(I ParameterList)
$(B ...)
$(GNAME Parameter):
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator)
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) $(B ...)
$(I InOut)$(OPT) $(GLINK BasicType) $(GLINK Declarator) = $(GLINK DefaultInitializerExpression)
$(I InOut)$(OPT) $(GLINK Type)
$(I InOut)$(OPT) $(GLINK Type) $(B ...)
$(GNAME InOut):
$(I InOutX)
$(I InOut InOutX)
$(GNAME InOutX):
$(B auto)
$(B const)
$(B final)
$(V2 $(B immutable)
) $(B in)
$(B inout)
$(B lazy)
$(B out)
$(B ref)
$(B scope)
$(B shared)
$(V2
$(GNAME FunctionAttributes):
$(GLINK FunctionAttribute)
$(GLINK FunctionAttribute) $(I FunctionAttributes)
$(GNAME FunctionAttribute):
$(B nothrow)
$(B pure)
$(GLINK Property)
)
$(GNAME MemberFunctionAttributes):
$(GLINK MemberFunctionAttribute)
$(GLINK MemberFunctionAttribute) $(I MemberFunctionAttributes)
$(GNAME MemberFunctionAttribute):
$(B const)
$(B immutable)
$(B inout)
$(B shared)
$(GLINK FunctionAttribute)
$(GNAME DefaultInitializerExpression):
$(ASSIGNEXPRESSION)
$(V2 $(B __FILE__)
$(B __LINE__))
$(GNAME Initializer):
$(GLINK VoidInitializer)
$(GLINK NonVoidInitializer)
$(GNAME NonVoidInitializer):
$(ASSIGNEXPRESSION)
$(GLINK ArrayInitializer)
$(GLINK StructInitializer)
$(GNAME ArrayInitializer):
$(B [ ])
$(B [) $(GLINK ArrayMemberInitializations) $(B ])
$(GNAME ArrayMemberInitializations):
$(GLINK ArrayMemberInitialization)
$(GLINK ArrayMemberInitialization) $(B ,)
$(GLINK ArrayMemberInitialization) $(B ,) $(I ArrayMemberInitializations)
$(GNAME ArrayMemberInitialization):
$(GLINK NonVoidInitializer)
$(ASSIGNEXPRESSION) $(B :) $(GLINK NonVoidInitializer)
$(GNAME StructInitializer):
$(B { })
$(B {) $(GLINK StructMemberInitializers) $(B })
$(GNAME StructMemberInitializers):
$(GLINK StructMemberInitializer)
$(GLINK StructMemberInitializer) $(B ,)
$(GLINK StructMemberInitializer) $(B ,) $(I StructMemberInitializers)
$(GNAME StructMemberInitializer):
$(GLINK NonVoidInitializer)
$(I Identifier) $(B :) $(GLINK 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
$(V1 C-style array, function pointer and pointer to array declarations are possible as an alternative:)
$(V2 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
--------------------
$(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
--------------------
$(GRAMMAR
$(GNAME AutoDeclaration):
$(GLINK StorageClasses) $(I AutoDeclarationX) $(B ;)
$(GNAME AutoDeclarationX):
$(I Identifier) $(B =) $(GLINK Initializer)
$(I AutoDeclarationX) $(B ,) $(I Identifier) $(B =) $(GLINK Initializer)
)
$(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
$(V1 auto s = "string"; // s is type char[6])
$(V2 auto s = "string"; // s is type immutable(char)[])
class C { ... }
auto c = new C(); // c is a handle to an instance of class C
----------
$(P 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.
)
$(V2
$(P An $(LINK2 expression.html#ArrayLiteral, $(I ArrayLiteral))
is inferred to be a dynamic array
type rather than a static array:)
---
auto v = ["hello", "world"]; // type is string[], not string[2]
---
)
$(V1
$(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
--------------------
)
$(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
--------------------
$(V1
$(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 $(SINGLEQUOTE import) a symbol from an import into the
current scope:
)
--------------------
$(B alias) string.strlen strlen;
--------------------
$(P
Aliases can also $(SINGLEQUOTE 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
-----------
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.
$(GRAMMAR
$(GNAME Typeof):
$(B typeof $(LPAREN)) $(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
OPT=opt
ASSIGNEXPRESSION=$(LINK2 expression.html#AssignExpression, $(I AssignExpression))
EXPRESSION=$(LINK2 expression.html#Expression, $(I Expression))
VEXPRESSION=$(V1 $(EXPRESSION))$(V2 $(ASSIGNEXPRESSION))
FOO=