[Home]
[Search]
[D]
Last modified Aug 29, 2004.
Declarations
Declaration:
typedef Decl
alias Decl
Decl
Decl:
StorageClass Decl
BasicType Declarators ;
BasicType Declarator FunctionBody
Declarators:
DeclaratorInitializer
DeclaratorInitializer , DeclaratorIdentifierList
DeclaratorInitializer:
Declarator
Declarator = Initializer
DeclaratorIdentifierList:
DeclaratorIdentifier
DeclaratorIdentifier , DeclaratorIdentifierList
DeclaratorIdentifier:
Identifier
Identifier = Initializer
BasicType:
bit
byte
ubyte
short
ushort
int
uint
long
ulong
char
wchar
dchar
float
double
real
ifloat
idouble
ireal
cfloat
cdouble
creal
void
.IdentifierList
IdentifierList
Typeof
Typeof . IdentifierList
BasicType2:
*
[ ]
[ Expression ]
[ Type ]
delegate ( ParameterList )
function ( ParameterList )
Declarator:
BasicType2 Declarator
Identifier
( Declarator )
Identifier DeclaratorSuffixes
( Declarator ) DeclaratorSuffixes
DeclaratorSuffixes:
DeclaratorSuffix
DeclaratorSuffix DeclaratorSuffixes
DeclaratorSuffix:
[ ]
[ Expression ]
[ Type ]
( ParameterList )
IdentifierList
Identifier
Identifier . IdentifierList
TemplateInstance
TemplateInstance . IdentifierList
Typeof
typeof ( Expression )
StorageClass:
abstract
auto
const
deprecated
final
override
static
synchronized
Type:
BasicType
BasicType Declarator2
Declarator2:
BasicType2 Declarator2
( Declarator2 )
( Declarator2 ) DeclaratorSuffixes
ParameterList:
Parameter
Paremeter , ParameterList
...
Parameter:
Declarator
Declarator = AssignExpression
InOut Declarator
InOut Declarator = AssignExpression
InOut:
in
out
inout
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 left to right:
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 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
In a declaration declaring multiple declarations, 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
Type Defining
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
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
Type aliases are equivalent to the C typedef.
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.
typeof
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*]
printf("%d\n", typeof('c').size); // 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
printf("%d\n", i); // prints 1
}
There are two special cases:
typeof(this) will generate the type of what this
would be in a non-static member function, even if not in a member
function.
Analogously, typeof(super) will generate the type of what
super would be in a non-static member 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.
Feedback and Comments
Add feedback and comments regarding this
page.
Copyright (c) 1999-2004 by Digital Mars, All Rights Reserved