www.digitalmars.com

D Programming Language 2.0


Last update Sun Dec 30 20:21:54 2012

Declarations

Declaration:
 AliasDeclaration
 AliasThisDeclaration
 Decl
AliasDeclaration:
 alias BasicType Declarator
 alias AliasInitializerList
AliasInitializerList:
 AliasInitializer
 AliasInitializer , AliasInitializerList
AliasInitializer:
 Identifier = Type
AliasThisDeclaration:
 alias Identifier this
 alias this = Identifier
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 MemberFunctionAttributes opt
 function Parameters FunctionAttributes opt
Declarator:
 BasicType2 opt ( Declarator ) DeclaratorSuffixes opt
 BasicType2 opt Identifier DeclaratorSuffixes opt
DeclaratorSuffixes:
 DeclaratorSuffix
 DeclaratorSuffix DeclaratorSuffixes
DeclaratorSuffix:
 [ ]
 [ AssignExpression ]
 [ Type ]
 TemplateParameterList opt Parameters MemberFunctionAttributes opt Constraint opt
IdentifierList:
 Identifier
 Identifier . IdentifierList
 TemplateInstance
 TemplateInstance . IdentifierList
StorageClasses:
 StorageClass
 StorageClass StorageClasses
StorageClass:
 abstract
 auto
 TypeCtor
 deprecated
 enum
 extern
 final
 nothrow
 override
 pure
 __gshared
 Property
 scope
 static
 synchronized
Property:
 @ PropertyIdentifier
PropertyIdentifier:
 property
 safe
 trusted
 system
 disable
TypeCtors:
 TypeCtor
 TypeCtor TypeCtors
TypeCtor:
 const
 immutable
 inout
 shared
Type:
 TypeCtors opt BasicType
 TypeCtors opt BasicType Declarator2
Declarator2:
 BasicType2 opt DeclaratorSuffixes opt
 BasicType2 opt ( Declarator2 ) DeclaratorSuffixes opt
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
 TypeCtor
 final
 in
 lazy
 out
 ref
 scope
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

AliasDeclarations create a symbol that is an alias for another type, and can be used anywhere that other type may appear.

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 {
 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

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.

Global and Static Initializers

The Initializer for a global or static variable must be evaluatable at compile time. Whether some pointers can be initialized with the addresses of other functions or data is implementation defined. Runtime initialization can be done with static constructors.





Forums | Comments | D | Search | Downloads | Home

AltStyle によって変換されたページ (->オリジナル) /