diff -uNr dmd-0.135/dmd/html/d/abi.html dmd-0.136/dmd/html/d/abi.html --- dmd-0.135/dmd/html/d/abi.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/abi.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,289 +1,345 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Application Binary Interface - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

D Application Binary Interface

- - A D implementation that conforms to the D ABI (Application Binary Interface) - will be able to generate libraries, DLL's, etc., that can interoperate with - D binaries built by other implementations. -

- - Most of this specification remains TBD (To Be Defined). - -

C ABI

- - The C ABI referred to in this specification means the C Application - Binary Interface of the target system. - C and D code should be freely linkable together, in particular, D - code shall have access to the entire C ABI runtime library. - -

Basic Types

- - TBD - -

Structs

- - Conforms to the target's C ABI struct layout. - -

Classes

- - An object consists of: - -
-	offset	contents
-	------  --------
-	0:	pointer to vtable
-	4:	monitor
-	8...	non-static members
-	
- - The vtable consists of: - -
-	0:	pointer to instance of ClassInfo
-	4...	pointers to virtual member functions
-	
- - The class definition: - -
-	class XXXX
-	{
-	    ....
-	};
-	
- - Generates the following: - -
    -
  • An instance of Class called ClassXXXX. - -
  • A type called StaticClassXXXX which defines all the static members. - -
  • An instance of StaticClassXXXX called StaticXXXX for the static members. -
- -

Interfaces

- - TBD - -

Arrays

- - A dynamic array consists of: - -
-	0:	array dimension
-	4:	pointer to array data
-	
- - A dynamic array is declared as: - -
-	type array[];
-	
- - whereas a static array is declared as: - -
-	type array[dimension];
-	
- - Thus, a static array always has the dimension statically available as part of the type, and - so it is implemented like in C. Static array's and Dynamic arrays can be easily converted back - and forth to each other. - - -

Associative Arrays

- - TBD - -

Reference Types

- - D has reference types, but they are implicit. For example, classes are always - referred to by reference; this means that class instances can never reside on the stack - or be passed as function parameters. -

- - When passing a static array to a function, the result, although declared as a static array, will - actually be a reference to a static array. For example: - -

-	int abc[3];
-	
- - Passing abc to functions results in these implicit conversions: - -
-	void func(int array[3]); // actually 
-	void func(int *p);       // abc[3] is converted to a pointer
-				 // to the first element
-	void func(int array[]);	 // abc[3] is converted to a dynamic array
-	
- - -

Name Mangling

- - TBD - -

Function Calling Conventions

- - TBD - -

Exception Handling

- -

Windows

- - Conforms to the Microsoft Windows Structured Exception Handling - conventions. - TBD - -

Linux

- - Uses static address range/handler tables. - TBD - -

Garbage Collection

- - TBD - -

Runtime Helper Functions

- - TBD - -

Module Initialization and Termination

- - TBD - -

Unit Testing

- - TBD - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Application Binary Interface + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

D Application Binary Interface

+ + A D implementation that conforms to the D ABI (Application Binary Interface) + will be able to generate libraries, DLL's, etc., that can interoperate with + D binaries built by other implementations. +

+ + Most of this specification remains TBD (To Be Defined). + +

C ABI

+ + The C ABI referred to in this specification means the C Application + Binary Interface of the target system. + C and D code should be freely linkable together, in particular, D + code shall have access to the entire C ABI runtime library. + +

Basic Types

+ + TBD + +

Structs

+ + Conforms to the target's C ABI struct layout. + +

Classes

+ + An object consists of: +

+ + + +
offset contents +
0 pointer to vtable +
4 monitor +
8... non-static members +
+

+ + The vtable consists of: +

+ + + +
offset contents +
0 pointer to instance of ClassInfo +
4... pointers to virtual member functions +
+

+ + The class definition: + +

class XXXX
+{
+    ....
+};
+
+ + Generates the following: + +
    +
  • An instance of Class called ClassXXXX. + +
  • A type called StaticClassXXXX which defines all the static members. + +
  • An instance of StaticClassXXXX called StaticXXXX for the static members. +
+ +

Interfaces

+ + TBD + +

Arrays

+ + A dynamic array consists of: +

+ + + +
offset contents +
0 array dimension +
4 pointer to array data +
+

+ + A dynamic array is declared as: + +

type array[];
+
+ + whereas a static array is declared as: + +
type array[dimension];
+
+ + Thus, a static array always has the dimension statically available as part of the type, and + so it is implemented like in C. Static array's and Dynamic arrays can be easily converted back + and forth to each other. + + +

Associative Arrays

+ + TBD + +

Reference Types

+ + D has reference types, but they are implicit. For example, classes are always + referred to by reference; this means that class instances can never reside on the stack + or be passed as function parameters. +

+ + When passing a static array to a function, the result, although declared as a static array, will + actually be a reference to a static array. For example: + +

int abc[3];
+
+ + Passing abc to functions results in these implicit conversions: + +
void func(int array[3]); // actually <reference to><array[3] of><int>
+void func(int *p);       // abc[3] is converted to a pointer
+			 // to the first element
+void func(int array[]);	 // abc[3] is converted to a dynamic array
+
+ + +

Name Mangling

+ + TBD + +

Function Calling Conventions

+ + TBD + +

Exception Handling

+ +

Windows

+ + Conforms to the Microsoft Windows Structured Exception Handling + conventions. + TBD + +

Linux

+ + Uses static address range/handler tables. + TBD + +

Garbage Collection

+ + TBD + +

Runtime Helper Functions

+ + TBD + +

Module Initialization and Termination

+ + TBD + +

Unit Testing

+ + TBD + + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/acknowledgements.html dmd-0.136/dmd/html/d/acknowledgements.html --- dmd-0.135/dmd/html/d/acknowledgements.html 2005-09-28 16:31:40.000000000 +0200 +++ dmd-0.136/dmd/html/d/acknowledgements.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,176 +1,224 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Acknowledgements - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Wed Sep 28 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - - -

Acknowledgements

- - -The following (incomplete) list of people have contributed to the D language -project; -with ideas, code, expertise, marketing, inspiration -and moral support. -

- Kris Bell, - Don Clugston, - Hauke Duden, - Bruce Eckel, - Eric Engstrom, - Dave Fladebo, - David Friedman, - Stewart Gordon, - Ben Hinkle, - Jan Knepper, - Thomas Kuehne, - Helmut Leitner, - Lubomir Litchev, - Christopher E. Miller, - Pavel Minayev, - Antonio Monteiro, - Paul Nash, - Pat Nelson, - Derek Parnell, - Burton Radons, - Tim Rentsch, - Fabio Riccardi, - Bob Taniguchi, - Bob W, - John Whited, - Matthew Wilson, - Peter Zatloukal - -

-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Acknowledgements + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:30 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ + · Overview
+ + + · D for Win32
+ + + · Win32 DLLs in D
+ + + · C .h to D Modules
+ + + · FAQ
+ + + · Style Guide
+ + + · Example: wc
+ + + · Future
+ + + · D Change Log
+ + + · Tech Tips
+ + + · Rationale
+ + + · Glossary
+ + + · Acknowledgements
+ + +
+ Tools +
+ · DMD D Compiler
+ + + · GDC D Compiler
+ + + · Linker
+ + + · Profiler
+ + +
+ Community +
+ · News Digest
+ + + · News
+ + + · Forum
+ + + · Announcements
+ + + · Learn
+ + + · D links
+ + +
+ Archives +
+ · digitalmars.D
+ + + · digitalmars.D.dtl
+ + + · digitalmars.D.announce
+ + + · digitalmars.D.learn
+ + + · digitalmars.D.bugs
+ + + · D.gnu
+ + + · Old D
+ + +
+
+
+ +

Acknowledgements

+ +

The following (incomplete) list of people have contributed to the D language +project; +with ideas, code, expertise, marketing, inspiration +and moral support. +

+ +

Kris Bell, + Don Clugston, + Hauke Duden, + Bruce Eckel, + Eric Engstrom, + Dave Fladebo, + David Friedman, + Stewart Gordon, + Ben Hinkle, + Jan Knepper, + Thomas Kuehne, + Helmut Leitner, + Lubomir Litchev, + Christopher E. Miller, + Pavel Minayev, + Antonio Monteiro, + Paul Nash, + Pat Nelson, + Derek Parnell, + Burton Radons, + Tim Rentsch, + Fabio Riccardi, + Bob Taniguchi, + Bob W, + John Whited, + Matthew Wilson, + Peter Zatloukal +

+ +
+ + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/arrays.html dmd-0.136/dmd/html/d/arrays.html --- dmd-0.135/dmd/html/d/arrays.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/arrays.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,1138 +1,1141 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Arrays - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

Arrays

- - There are four kinds of arrays: - - -
int* p; Pointers to data - -
int[3] s; Static arrays - -
int[] a; Dynamic arrays - -
int[char[]] x; Associative arrays -
- -

Pointers

- -
-	int* p;
-	
- - These are simple pointers to data, analogous to C pointers. - Pointers are provided for interfacing with C and for - specialized systems work. - There - is no length associated with it, and so there is no way for the - compiler or runtime to do bounds checking, etc., on it. - Most conventional uses for pointers can be replaced with - dynamic arrays, out and inout parameters, - and reference types. - -

Static Arrays

- -
-	int[3] s;
-	
- - These are analogous to C arrays. Static arrays are distinguished - by having a length fixed at compile time. -

- - The total size of a static array cannot exceed 16Mb. - A dynamic array should be used instead for such large arrays. - -

Dynamic Arrays

- -
-	int[] a;
-	
- - Dynamic arrays consist of a length and a pointer to the array data. - Multiple dynamic arrays can share all or parts of the array data. - -

Array Declarations

- - There are two ways to declare arrays, prefix and postfix. - The prefix form is the preferred method, especially for - non-trivial types. - -

Prefix Array Declarations

- - Prefix declarations appear before the identifier being - declared and read right to left, so: - -
-	int[] a;	// dynamic array of ints
-	int[4][3] b;	// array of 3 arrays of 4 ints each
-	int[][5] c;	// array of 5 dynamic arrays of ints.
-	int*[]*[3] d;	// array of 3 pointers to dynamic arrays of pointers to ints
-	int[]* e;	// pointer to dynamic array of ints
-	
- - -

Postfix Array Declarations

- - Postfix declarations appear after the identifier being - declared and read left to right. - Each group lists equivalent declarations: - -
-	// dynamic array of ints
-	int[] a;
-	int a[];
-
-	// array of 3 arrays of 4 ints each
-	int[4][3] b;
-	int[4] b[3];
-	int b[3][4];
-
-	// array of 5 dynamic arrays of ints.
-	int[][5] c;
-	int[] c[5];
-	int c[5][];
-
-	// array of 3 pointers to dynamic arrays of pointers to ints
-	int*[]*[3] d;
-	int*[]* d[3];
-	int* (*d[3])[];
-
-	// pointer to dynamic array of ints
-	int[]* e;
-	int (*e[]);
-	
- - Rationale: The postfix form matches the way arrays are - declared in C and C++, and supporting this form provides an - easy migration path for programmers used to it. - -

Usage

- - There are two broad kinds of operations to do on an array - affecting - the handle to the array, - and affecting the contents of the array. - C only has - operators to affect the handle. In D, both are accessible. -

- - The handle to an array is specified by naming the array, as - in p, s or a: - -

-	int* p;
-	int[3] s;
-	int[] a;
-
-	int* q;
-	int[3] t;
-	int[] b;
-
-	p = q;		p points to the same thing q does.
-	p = s;		p points to the first element of the array s.
-	p = a;		p points to the first element of the array a.
-
-	s = ...;	error, since s is a compiled in static
-			reference to an array.
-
-	a = p;		error, since the length of the array pointed
-			to by p is unknown
-	a = s;		a is initialized to point to the s array
-	a = b;		a points to the same array as b does
-    
- -

Slicing

- - Slicing an array means to specify a subarray of it. - An array slice does not copy the data, it is only another - reference to it. - For example: - -
-	int[10] a;	// declare array of 10 ints
-	int[] b;
-
-	b = a[1..3];	// a[1..3] is a 2 element array consisting of
-			// a[1] and a[2]
-	foo(b[1]);	// equivalent to foo(0)
-	a[2] = 3;
-	foo(b[1]);	// equivalent to foo(3)
-    
- - The [] is shorthand for a slice of the entire array. - For example, the assignments to b: - -
-	int[10] a;
-	int[] b;
-
-	b = a;
-	b = a[];
-	b = a[0 .. a.length];
-    
- are all semantically equivalent. -

- - Slicing - is not only handy for referring to parts of other arrays, - but for converting pointers into bounds-checked arrays: - -

-	int* p;
-	int[] b = p[0..8];
-    
- - Slicing for bit arrays is only allowed if the slice's lower - bound falls on a byte boundary: - -
-	bit[] b;
-	...
-	b[0..8];	// ok
-	b[8..16];	// ok
-	b[8..17];	// ok
-	b[1..16];	// error, lower bound is not on a byte boundary
-    
- - Misaligned bit array slices will cause an ArrayBoundsError exception - to be thrown at runtime. - -

Array Copying

- - When the slice operator appears as the lvalue of an assignment - expression, it means that the contents of the array are the - target of the assignment rather than a reference to the array. - Array copying happens when the lvalue is a slice, and the rvalue - is an array of or pointer to the same type. - -
-	int[3] s;
-	int[3] t;
-
-	s[] = t;		the 3 elements of t[3] are copied into s[3]
-	s[] = t[];		the 3 elements of t[3] are copied into s[3]
-	s[1..2] = t[0..1];	same as s[1] = t[0]
-	s[0..2] = t[1..3];	same as s[0] = t[1], s[1] = t[2]
-	s[0..4] = t[0..4];	error, only 3 elements in s
-	s[0..2] = t;		error, different lengths for lvalue and rvalue
-    
- - Overlapping copies are an error: - -
-	s[0..2] = s[1..3];	error, overlapping copy
-	s[1..3] = s[0..2];	error, overlapping copy
- - Disallowing overlapping makes it possible for more aggressive - parallel code optimizations than possible with the serial - semantics of C. - -

Array Setting

- - If a slice operator appears as the lvalue of an assignment - expression, and the type of the rvalue is the same as the element - type of the lvalue, then the lvalue's array contents - are set to the rvalue. - -
-	int[3] s;
-	int* p;
-
-	s[] = 3;		same as s[0] = 3, s[1] = 3, s[2] = 3
-	p[0..2] = 3;		same as p[0] = 3, p[1] = 3
-    
- -

Array Concatenation

- - The binary operator ~ is the cat operator. It is used - to concatenate arrays: - -
-
-	int[] a;
-	int[] b;
-	int[] c;
-
-	a = b ~ c;	Create an array from the concatenation of the
-			b and c arrays
-    
- - Many languages overload the + operator to mean concatenation. - This confusingly leads to, does: - -
-	"10" + 3
-    
- - produce the number 13 or the string "103" as the result? It isn't - obvious, and the language designers wind up carefully writing rules - to disambiguate it - rules that get incorrectly implemented, - overlooked, forgotten, and ignored. It's much better to have + mean - addition, and a separate operator to be array concatenation. -

- - Similarly, the ~= operator means append, as in: - -

-	a ~= b;		a becomes the concatenation of a and b
-    
- - Concatenation always creates a copy of its operands, even - if one of the operands is a 0 length array, so: - -
-	a = b			a refers to b
-	a = b ~ c[0..0]		a refers to a copy of b
-    
- - - -

Array Operations

- - Note: Array operations are not implemented. -

- - In general, (a[n..m] op e) is defined as: - -

-	for (i = n; i < m; i++)
-	    a[i] op e;
-    
- - So, for the expression: - -
-	a[] = b[] + 3;
-    
- - the result is equivalent to: - -
-	for (i = 0; i < a.length; i++)
-	    a[i] = b[i] + 3; 
-    
- - When more than one [] operator appears in an expression, the range - represented by all must match. - -
-	a[1..3] = b[] + 3;	error, 2 elements not same as 3 elements
-    
- -

Examples:

- -
-	int[3] abc;			// static array of 3 ints
-	int[] def = [ 1, 2, 3 ];	// dynamic array of 3 ints
-
-	void dibb(int *array)
-	{
-		array[2];		// means same thing as *(array + 2)
-		*(array + 2);		// get 2nd element
-	}
-
-	void diss(int[] array)
-	{
-		array[2];		// ok
-		*(array + 2);		// error, array is not a pointer
-	}
-
-	void ditt(int[3] array)
-	{
-		array[2];		// ok
-		*(array + 2);		// error, array is not a pointer
-	}
-	
- -

Rectangular Arrays

- - Experienced FORTRAN numerics programmers know that multidimensional - "rectangular" arrays for things like matrix operations are much faster than trying to - access them via pointers to pointers resulting from "array of pointers to array" semantics. - For example, the D syntax: - -
-	double[][] matrix;
-	
- - declares matrix as an array of pointers to arrays. (Dynamic arrays are implemented as - pointers to the array data.) Since the arrays can have varying sizes (being dynamically - sized), this is sometimes called "jagged" arrays. Even worse for optimizing the code, the - array rows can sometimes point to each other! Fortunately, D static arrays, while using - the same syntax, are implemented as a fixed rectangular layout: - -
-	double[3][3] matrix;
-	
- - declares a rectangular matrix with 3 rows and 3 columns, all contiguously in memory. In - other languages, this would be called a multidimensional array and be declared as: - -
-	double matrix[3,3];
-	
- -

Array Length

- - Within the [ ] of a static or a dynamic array, - the variable length - is implicitly declared and set to the length of the array. - -
-	int[4] foo;
-	int[]  bar = foo;
-	int*   p = &foo[0];
-
-	// These expressions are equivalent:
-	bar[]
-	bar[0 .. 4]
-	bar[0 .. length]
-	bar[0 .. bar.length]
-
-	p[0 .. length]	// 'length' is not defined, since p is not an array
-	bar[0]+length	// 'length' is not defined, out of scope of [ ]
-
-	bar[length-1]	// retrieves last element of the array
-	
- -

Array Properties

- - Static array properties are: - - - - - - - -
.sizeof - Returns the array length multiplied by the number of - bytes per array element. - -
.length - Returns the number of elements in the array. - This is a fixed quantity for static arrays. - -
.ptr - Returns a pointer to the first element of the array. - -
.dup - Create a dynamic array of the same size - and copy the contents of the array into it. - -
.reverse - Reverses in place the order of the elements in the array. - Returns the array. - -
.sort - Sorts in place the order of the elements in the array. - Returns the array. - -
-

- - Dynamic array properties are: - - - - - - - - -
.sizeof - Returns the size of the dynamic array reference, - which is 8 on 32 bit machines. - -
.length - Get/set number of elements in the array. - -
.ptr - Returns a pointer to the first element of the array. - -
.dup - Create a dynamic array of the same size - and copy the contents of the array into it. - -
.reverse - Reverses in place the order of the elements in the array. - Returns the array. - -
.sort - Sorts in place the order of the elements in the array. - Returns the array. - -
-

- - Examples: -

-	p.length	error, length not known for pointer
-	s.length	compile time constant 3
-	a.length	runtime value
-
-	p.dup		error, length not known
-	s.dup		creates an array of 3 elements, copies
-			elements s into it
-	a.dup		creates an array of a.length elements, copies
-			elements of a into it
-    
- -

Setting Dynamic Array Length

- - The .length property of a dynamic array can be set - as the lvalue of an = operator: -
-	array.length = 7;
-	
- - This causes the array to be reallocated in place, and the existing - contents copied over to the new array. If the new array length is - shorter, - only enough are copied to fill the new array. If the new array length - is longer, the remainder is filled out with the default initializer. -

- - To maximize efficiency, the runtime always tries to resize the - array in place to avoid extra copying. It will always do a copy - if the new size is larger and the array was not allocated via the - new operator or a previous - resize operation. -

- - This means that if there is an array slice immediately following the - array being resized, the resized array could overlap the slice; i.e.: -

-	char[] a = new char[20];
-	char[] b = a[0..10];
-	char[] c = a[10..20];
-
-	b.length = 15;	// always resized in place because it is sliced
-			// from a[] which has enough memory for 15 chars
-	b[11] = 'x';	// a[15] and c[5] are also affected
-
-	a.length = 1;
-	a.length = 20;	// no net change to memory layout
-
-	c.length = 12;	// always does a copy because c[] is not at the
-			// start of a gc allocation block
-	c[5] = 'y';	// does not affect contents of a[] or b[]
-
-	a.length = 25;	// may or may not do a copy
-	a[3] = 'z';	// may or may not affect b[3] which still overlaps
-			// the old a[3]
-	
- - To guarantee copying behavior, use the .dup property to ensure - a unique array that can be resized. -

- - These issues also apply to concatenating arrays with the ~ and ~= - operators. -

- - Resizing a dynamic array is a relatively expensive operation. - So, while the following method of filling an array: -

-
-	int[] array;
-	while (1)
-	{   c = getinput();
-	    if (!c)
-	       break;
-	    array.length = array.length + 1;
-	    array[array.length - 1] = c;
-	}
-	
- - will work, it will be inefficient. A more practical - approach would be to minimize the number of resizes: - -
-	int[] array;
-	array.length = 100;        // guess
-	for (i = 0; 1; i++)
-	{   c = getinput();
-	     if (!c)
-		break;
-	     if (i == array.length)
-		array.length = array.length * 2;
-	     array[i] = c;
-	}
-	array.length = i;
-	
- - Picking a good initial guess is an art, but you usually can - pick a value covering 99% of the cases. - For example, when gathering user - input from the console - it's unlikely to be longer than 80. - -

Array Bounds Checking

- - It is an error to index an array with an index that is less than - 0 or greater than or equal to the array length. If an index is - out of bounds, an ArrayBoundsError exception is raised if detected - at runtime, and an error if detected at compile time. - A program may not rely on array bounds checking happening, for - example, the following program is incorrect: - -
-	try
-	{
-	    for (i = 0; ; i++)
-	    {
-		array[i] = 5;
-	    }
-	}
-	catch (ArrayBoundsError)
-	{
-	    // terminate loop
-	}
-	
- - The loop is correctly written: - -
-	for (i = 0; i < array.length; i++)
-	{
-	    array[i] = 5;
-	}
-	
- - Implementation Note: Compilers should attempt to detect - array bounds errors at compile time, for example: - -
-	int[3] foo;
-	int x = foo[3];		// error, out of bounds
-	
- - Insertion of array bounds checking code at runtime should be - turned on and off - with a compile time switch. - -

Array Initialization

- -

Default Initialization

- -
    -
  • Pointers are initialized to null. -
  • Static array contents are initialized to the default - initializer for the array element type. -
  • Dynamic arrays are initialized to having 0 elements. -
  • Associative arrays are initialized to having 0 elements. -
- -

Void Initialization

- - Void initialization happens when the Initializer for - an array is void. What it means is that no initialization - is done, i.e. the contents of the array will be undefined. - This is most useful as an efficiency optimization. - Void initializations are an advanced technique and should only be used - when profiling indicates that it matters. - -

Static Initialization of Static Arrays

- -
-	int[3] a = [ 1:2, 3 ];		// a[0] = 0, a[1] = 2, a[2] = 3
-	
- - This is most handy when the array indices are given by enums: - -
-	enum Color { red, blue, green };
-
-	int value[Color.max + 1] = [ blue:6, green:2, red:5 ];
-	
- - If any members of an array are initialized, they all must be. - This is to catch - common errors where another element is added to an enum, - but one of the static instances - of arrays of that enum was overlooked in updating the - initializer list. - - -

Special Array Types

- -

Arrays of Bits

- - Bit vectors can be constructed: - -
-	bit[10] x;		// array of 10 bits
-	
- - The amount of storage used up is implementation dependent. - Implementation Note: on - Intel CPUs it would be rounded up to the next 32 bit size. - -
-	x.length		// 10, number of bits
-	x.size			// 4,  bytes of storage
-	
- - So, the size per element is not (x.size / x.length). - - - -

Strings

- - Languages should be good at handling strings. C and C++ are not - good at it. The primary difficulties are memory management, - handling of temporaries, constantly rescanning the string looking - for the terminating 0, and the fixed arrays. -

- - Dynamic arrays in D suggest the obvious solution - a string is - just a dynamic array of characters. String literals become just - an easy way to write character arrays. - -

-	char[] str;
-	char[] str1 = "abc";
-	
- - char[] strings are in UTF-8 format. - wchar[] strings are in UTF-16 format. - dchar[] strings are in UTF-32 format. -

- - Strings can be copied, compared, concatenated, and appended: - -

-	str1 = str2;
-	if (str1 < str3) ...
-	func(str3 ~ str4);
-	str4 ~= str1;
-	
- - with the obvious semantics. Any generated temporaries get cleaned up - by the garbage collector (or by using alloca()). Not only that, - this works with any - array not just a special String array. -

- - A pointer to a char can be generated: - -

-	char *p = &str[3];	// pointer to 4th element
-	char *p = str;		// pointer to 1st element
-	
- - Since strings, however, are not 0 terminated in D, - when transferring a pointer - to a string to C, add a terminating 0: - -
-	str ~= "\0";
-	
- - The type of a string is determined by the semantic phase of - compilation. The type is - one of: char[], wchar[], dchar[], and is determined by - implicit conversion rules. - If there are two equally applicable implicit conversions, - the result is an error. To - disambiguate these cases, a cast is appropriate: - -
-	cast(wchar [])"abc"	// this is an array of wchar characters
-	
- - String literals are implicitly converted between chars, - wchars, and dchars as necessary. -

- - Strings a single character in length can also be exactly - converted to a char, wchar or dchar constant: - -

-	char c;
-	wchar w;
-	dchar d;
-
-	c = 'b';		// c is assigned the character 'b'
-	w = 'b';		// w is assigned the wchar character 'b'
-	w = 'bc';		// error - only one wchar character at a time
-	w = "b"[0];		// w is assigned the wchar character 'b'
-	w = \r;			// w is assigned the carriage return wchar character
-	d = 'd';		// d is assigned the character 'd'
-	
- -

printf() and Strings

- - printf() is a C function and is not part of D. printf() - will print C strings, which are 0 terminated. There are two ways - to use printf() with D strings. The first is to add a - terminating 0, and cast the result to a char*: - -
-	str ~= "\0";
-	printf("the string is '%s'\n", (char *)str);
-	
- - The second way is to use the precision specifier. The way D arrays - are laid out, the length comes first, so the following works: - -
-	printf("the string is '%.*s'\n", str);
-	
- - In the future, it may be necessary to just add a new format - specifier to printf() instead of relying on an implementation - dependent detail. - -

Implicit Conversions

- - A pointer T* can be implicitly converted to - one of the following: - -
    -
  • U* where U is a base class of T. -
  • void* -
- - A static array T[dim] can be implicitly - converted to - one of the following: - -
    -
  • T* -
  • T[] -
  • U[dim] where U is a base class of T. -
  • U[] where U is a base class of T. -
  • U* where U is a base class of T. -
  • void* -
  • void[] -
- - A dynamic array T[] can be implicitly converted to - one of the following: - -
    -
  • T* -
  • U[] where U is a base class of T. -
  • U* where U is a base class of T. -
  • void* -
- - - -
-

Associative Arrays

- - D goes one step further with arrays - adding associative arrays. - Associative arrays have an index that is not necessarily an integer, - and can be sparsely populated. The index for an associative array - is called the key, and its type is called the KeyType. -

- - Associative arrays are declared by placing the KeyType - within the [] of an array declaration: - -

-	int[char[]] b;		// associative array b of ints that are
-				// indexed by an array of characters.
-				// The KeyType is char[]
-	b["hello"] = 3;		// set value associated with key "hello" to 3
-	func(b["hello"]);	// pass 3 as parameter to func()
-	
- - Particular keys in an associative array can be removed with the - remove function: - -
-	b.remove("hello");
-	
- - The InExpression yields a pointer to the value - if the key is in the associative array, or null if not: - -
-	int* p;
-	p = ("hello" in b);
-	if (p != null)
-		...
-	
- - KeyTypes cannot be functions or voids. -

- - If the KeyType is a struct type, a default mechanism is used - to compute the hash and comparisons of it based on the binary - data within the struct value. A custom mechanism can be used - by providing the following functions as struct members: - -

-	uint toHash();
-	int opCmp(KeyType* s);
-	
- - For example: - -
-	import std.string;
-
-	struct MyString
-	{
-	    char[] str;
-
-	    uint toHash()
-	    {	uint hash;
-		foreach (char c; s)
-		    hash = (hash * 9) + c;
-		return hash;
-	    }
-
-	    int opCmp(MyString* s)
-	    {
-		return std.string.cmp(this.str, s.str);
-	    }
-	}
-	
- -

Properties

- -Properties for associative arrays are: - - - - - - - - -
.size - Returns the size of the reference to the associative - array; it is typically 8. - -
.length - Returns number of values in the associative array. - Unlike for dynamic arrays, it is read-only. - -
.keys - Returns dynamic array, the elements of which are the keys in - the associative array. - -
.values - Returns dynamic array, the elements of which are the values in - the associative array. - -
.rehash - Reorganizes the associative array in place so that lookups - are more efficient. rehash is effective when, for example, - the program is done loading up a symbol table and now needs - fast lookups in it. - Returns a reference to the reorganized array. - -
- -
-

Associative Array Example: word count

- -
-    import std.file;		// D file I/O
-
-    int main (char[][] args)
-    {
-	int word_total;
-	int line_total;
-	int char_total;
-	int[char[]] dictionary;
-
-	printf("   lines   words   bytes file\n");
-	for (int i = 1; i < args.length; ++i)	// program arguments
-	{
-	    char[] input;		// input buffer
-	    int w_cnt, l_cnt, c_cnt;	// word, line, char counts
-	    int inword;
-	    int wstart;
-
-	    input = std.file.read(args[i]);	// read file into input[]
-
-	    foreach (char c; input)
-	    {
-		if (c == '\n')
-		    ++l_cnt;
-		if (c >= '0' && c <= '9')
-		{
-		}
-		else if (c >= 'a' && c <= 'z' ||
-		    c >= 'A' && c <= 'Z')
-		{
-		    if (!inword)
-		    {
-			wstart = j;
-			inword = 1;
-			++w_cnt;
-		    }
-		}
-		else if (inword)
-		{   char[] word = input[wstart .. j];
-
-		    dictionary[word]++;		// increment count for word
-		    inword = 0;
-		}
-		++c_cnt;
-	    }
-	    if (inword)
-	    {   char[] word = input[wstart .. input.length];
-		dictionary[word]++;
-	    }
-	    printf("%8ld%8ld%8ld %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
-	    line_total += l_cnt;
-	    word_total += w_cnt;
-	    char_total += c_cnt;
-	}
-
-	if (args.length > 2)
-	{
-	    printf("-------------------------------------\n%8ld%8ld%8ld total",
-		line_total, word_total, char_total);
-	}
-
-	printf("-------------------------------------\n");
-	char[][] keys = dictionary.keys;	// find all words in dictionary[]
-	for (int i = 0; i < keys.length; i++)
-	{   char[] word;
-
-	    word = keys[i];
-	    printf("%3d %.*s\n", dictionary[word], word);
-	}
-	return 0;
-    }
-    
- -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - - + + + + + + + + +D Programming Language - Arrays + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

Arrays

+ + There are four kinds of arrays: +

+ + +
int* p; Pointers to data + +
int[3] s; Static arrays + +
int[] a; Dynamic arrays + +
int[char[]] x; Associative arrays +
+ +

Pointers

+ +
int* p;
+
+ + These are simple pointers to data, analogous to C pointers. + Pointers are provided for interfacing with C and for + specialized systems work. + There + is no length associated with it, and so there is no way for the + compiler or runtime to do bounds checking, etc., on it. + Most conventional uses for pointers can be replaced with + dynamic arrays, out and inout parameters, + and reference types. + +

Static Arrays

+ +
int[3] s;
+
+ + These are analogous to C arrays. Static arrays are distinguished + by having a length fixed at compile time. +

+ + The total size of a static array cannot exceed 16Mb. + A dynamic array should be used instead for such large arrays. + +

Dynamic Arrays

+ +
int[] a;
+
+ + Dynamic arrays consist of a length and a pointer to the array data. + Multiple dynamic arrays can share all or parts of the array data. + +

Array Declarations

+ + There are two ways to declare arrays, prefix and postfix. + The prefix form is the preferred method, especially for + non-trivial types. + +

Prefix Array Declarations

+ + Prefix declarations appear before the identifier being + declared and read right to left, so: + +
int[] a;	// dynamic array of ints
+int[4][3] b;	// array of 3 arrays of 4 ints each
+int[][5] c;	// array of 5 dynamic arrays of ints.
+int*[]*[3] d;	// array of 3 pointers to dynamic arrays of pointers to ints
+int[]* e;	// pointer to dynamic array of ints
+
+ + +

Postfix Array Declarations

+ + Postfix declarations appear after the identifier being + declared and read left to right. + Each group lists equivalent declarations: + +
// dynamic array of ints
+int[] a;
+int a[];
+
+// array of 3 arrays of 4 ints each
+int[4][3] b;
+int[4] b[3];
+int b[3][4];
+
+// array of 5 dynamic arrays of ints.
+int[][5] c;
+int[] c[5];
+int c[5][];
+
+// array of 3 pointers to dynamic arrays of pointers to ints
+int*[]*[3] d;
+int*[]* d[3];
+int* (*d[3])[];
+
+// pointer to dynamic array of ints
+int[]* e;
+int (*e[]);
+
+ + Rationale: The postfix form matches the way arrays are + declared in C and C++, and supporting this form provides an + easy migration path for programmers used to it. + +

Usage

+ + There are two broad kinds of operations to do on an array - affecting + the handle to the array, + and affecting the contents of the array. + C only has + operators to affect the handle. In D, both are accessible. +

+ + The handle to an array is specified by naming the array, as + in p, s or a: + +

int* p;
+int[3] s;
+int[] a;
+
+int* q;
+int[3] t;
+int[] b;
+
+p = q;		// p points to the same thing q does.
+p = s;		// p points to the first element of the array s.
+p = a;		// p points to the first element of the array a.
+
+s = ...;	// error, since s is a compiled in static
+		// reference to an array.
+
+a = p;		// error, since the length of the array pointed
+		// to by p is unknown
+a = s;		// a is initialized to point to the s array
+a = b;		// a points to the same array as b does
+
+ +

Slicing

+ + Slicing an array means to specify a subarray of it. + An array slice does not copy the data, it is only another + reference to it. + For example: + +
int[10] a;	// declare array of 10 ints
+int[] b;
+
+b = a[1..3];	// a[1..3] is a 2 element array consisting of
+		// a[1] and a[2]
+foo(b[1]);	// equivalent to foo(0)
+a[2] = 3;
+foo(b[1]);	// equivalent to foo(3)
+
+ + The [] is shorthand for a slice of the entire array. + For example, the assignments to b: + +
int[10] a;
+int[] b;
+
+b = a;
+b = a[];
+b = a[0 .. a.length];
+
+ + are all semantically equivalent. +

+ + Slicing + is not only handy for referring to parts of other arrays, + but for converting pointers into bounds-checked arrays: + +

int* p;
+int[] b = p[0..8];
+
+ + Slicing for bit arrays is only allowed if the slice's lower + bound falls on a byte boundary: + +
bit[] b;
+...
+b[0..8];	// ok
+b[8..16];	// ok
+b[8..17];	// ok
+b[1..16];	// error, lower bound is not on a byte boundary
+
+ + Misaligned bit array slices will cause an ArrayBoundsError exception + to be thrown at runtime. + +

Array Copying

+ + When the slice operator appears as the lvalue of an assignment + expression, it means that the contents of the array are the + target of the assignment rather than a reference to the array. + Array copying happens when the lvalue is a slice, and the rvalue + is an array of or pointer to the same type. + +
int[3] s;
+int[3] t;
+
+s[] = t;		// the 3 elements of t[3] are copied into s[3]
+s[] = t[];		// the 3 elements of t[3] are copied into s[3]
+s[1..2] = t[0..1];	// same as s[1] = t[0]
+s[0..2] = t[1..3];	// same as s[0] = t[1], s[1] = t[2]
+s[0..4] = t[0..4];	// error, only 3 elements in s
+s[0..2] = t;		// error, different lengths for lvalue and rvalue
+
+ + Overlapping copies are an error: + +
s[0..2] = s[1..3];	// error, overlapping copy
+s[1..3] = s[0..2];	// error, overlapping copy
+
+ + Disallowing overlapping makes it possible for more aggressive + parallel code optimizations than possible with the serial + semantics of C. + +

Array Setting

+ + If a slice operator appears as the lvalue of an assignment + expression, and the type of the rvalue is the same as the element + type of the lvalue, then the lvalue's array contents + are set to the rvalue. + +
int[3] s;
+int* p;
+
+s[] = 3;		// same as s[0] = 3, s[1] = 3, s[2] = 3
+p[0..2] = 3;		// same as p[0] = 3, p[1] = 3
+
+ +

Array Concatenation

+ + The binary operator ~ is the cat operator. It is used + to concatenate arrays: + +
int[] a;
+int[] b;
+int[] c;
+
+a = b ~ c;	// Create an array from the concatenation of the
+		// b and c arrays
+
+ + Many languages overload the + operator to mean concatenation. + This confusingly leads to, does: + +
"10" + 3
+
+ + produce the number 13 or the string "103" as the result? It isn't + obvious, and the language designers wind up carefully writing rules + to disambiguate it - rules that get incorrectly implemented, + overlooked, forgotten, and ignored. It's much better to have + mean + addition, and a separate operator to be array concatenation. +

+ + Similarly, the ~= operator means append, as in: + +

a ~= b;		// a becomes the concatenation of a and b
+
+ + Concatenation always creates a copy of its operands, even + if one of the operands is a 0 length array, so: + +
a = b;			// a refers to b
+a = b ~ c[0..0];	// a refers to a copy of b
+
+ + + +

Array Operations

+ + Note: Array operations are not implemented. +

+ + In general, (a[n..m] op e) is defined as: + +

for (i = n; i < m; i++)
+    a[i] op e;
+
+ + So, for the expression: + +
a[] = b[] + 3;
+
+ + the result is equivalent to: + +
for (i = 0; i < a.length; i++)
+    a[i] = b[i] + 3; 
+
+ + When more than one [] operator appears in an expression, the range + represented by all must match. + +
a[1..3] = b[] + 3;	// error, 2 elements not same as 3 elements
+
+ +

Examples:

+ +
int[3] abc;			// static array of 3 ints
+int[] def = [ 1, 2, 3 ];	// dynamic array of 3 ints
+
+void dibb(int *array)
+{
+	array[2];		// means same thing as *(array + 2)
+	*(array + 2);		// get 2nd element
+}
+
+void diss(int[] array)
+{
+	array[2];		// ok
+	*(array + 2);		// error, array is not a pointer
+}
+
+void ditt(int[3] array)
+{
+	array[2];		// ok
+	*(array + 2);		// error, array is not a pointer
+}
+
+ +

Rectangular Arrays

+ + Experienced FORTRAN numerics programmers know that multidimensional + "rectangular" arrays for things like matrix operations are much faster than trying to + access them via pointers to pointers resulting from "array of pointers to array" semantics. + For example, the D syntax: + +
double[][] matrix;
+
+ + declares matrix as an array of pointers to arrays. (Dynamic arrays are implemented as + pointers to the array data.) Since the arrays can have varying sizes (being dynamically + sized), this is sometimes called "jagged" arrays. Even worse for optimizing the code, the + array rows can sometimes point to each other! Fortunately, D static arrays, while using + the same syntax, are implemented as a fixed rectangular layout: + +
double[3][3] matrix;
+
+ + declares a rectangular matrix with 3 rows and 3 columns, all contiguously in memory. In + other languages, this would be called a multidimensional array and be declared as: + +
double matrix[3,3];
+
+ +

Array Length

+ + Within the [ ] of a static or a dynamic array, + the variable length + is implicitly declared and set to the length of the array. + +
int[4] foo;
+int[]  bar = foo;
+int*   p = &foo[0];
+
+// These expressions are equivalent:
+bar[]
+bar[0 .. 4]
+bar[0 .. length]
+bar[0 .. bar.length]
+
+p[0 .. length]		// 'length' is not defined, since p is not an array
+bar[0]+length		// 'length' is not defined, out of scope of [ ]
+
+bar[length-1]	// retrieves last element of the array
+
+ +

Array Properties

+ + Static array properties are: + + + + + + + +
.sizeof + Returns the array length multiplied by the number of + bytes per array element. + +
.length + Returns the number of elements in the array. + This is a fixed quantity for static arrays. + +
.ptr + Returns a pointer to the first element of the array. + +
.dup + Create a dynamic array of the same size + and copy the contents of the array into it. + +
.reverse + Reverses in place the order of the elements in the array. + Returns the array. + +
.sort + Sorts in place the order of the elements in the array. + Returns the array. + +
+

+ + Dynamic array properties are: + + + + + + + + +
.sizeof + Returns the size of the dynamic array reference, + which is 8 on 32 bit machines. + +
.length + Get/set number of elements in the array. + +
.ptr + Returns a pointer to the first element of the array. + +
.dup + Create a dynamic array of the same size + and copy the contents of the array into it. + +
.reverse + Reverses in place the order of the elements in the array. + Returns the array. + +
.sort + Sorts in place the order of the elements in the array. + Returns the array. + +
+

+ + Examples: + +

p.length	// error, length not known for pointer
+s.length	// compile time constant 3
+a.length	// runtime value
+
+p.dup		// error, length not known
+s.dup		// creates an array of 3 elements, copies
+		// elements s into it
+a.dup		// creates an array of a.length elements, copies
+		// elements of a into it
+
+ +

Setting Dynamic Array Length

+ + The .length property of a dynamic array can be set + as the lvalue of an = operator: + +
array.length = 7;
+
+ + This causes the array to be reallocated in place, and the existing + contents copied over to the new array. If the new array length is + shorter, + only enough are copied to fill the new array. If the new array length + is longer, the remainder is filled out with the default initializer. +

+ + To maximize efficiency, the runtime always tries to resize the + array in place to avoid extra copying. It will always do a copy + if the new size is larger and the array was not allocated via the + new operator or a previous + resize operation. +

+ + This means that if there is an array slice immediately following the + array being resized, the resized array could overlap the slice; i.e.: + +

char[] a = new char[20];
+char[] b = a[0..10];
+char[] c = a[10..20];
+
+b.length = 15;	// always resized in place because it is sliced
+		// from a[] which has enough memory for 15 chars
+b[11] = 'x';	// a[15] and c[5] are also affected
+
+a.length = 1;
+a.length = 20;	// no net change to memory layout
+
+c.length = 12;	// always does a copy because c[] is not at the
+		// start of a gc allocation block
+c[5] = 'y';	// does not affect contents of a[] or b[]
+
+a.length = 25;	// may or may not do a copy
+a[3] = 'z';	// may or may not affect b[3] which still overlaps
+		// the old a[3]
+
+ + To guarantee copying behavior, use the .dup property to ensure + a unique array that can be resized. +

+ + These issues also apply to concatenating arrays with the ~ and ~= + operators. +

+ + Resizing a dynamic array is a relatively expensive operation. + So, while the following method of filling an array: + +

int[] array;
+while (1)
+{   c = getinput();
+    if (!c)
+       break;
+    array.length = array.length + 1;
+    array[array.length - 1] = c;
+}
+
+ + will work, it will be inefficient. A more practical + approach would be to minimize the number of resizes: + +
int[] array;
+array.length = 100;        // guess
+for (i = 0; 1; i++)
+{   c = getinput();
+     if (!c)
+	break;
+     if (i == array.length)
+	array.length = array.length * 2;
+     array[i] = c;
+}
+array.length = i;
+
+ + Picking a good initial guess is an art, but you usually can + pick a value covering 99% of the cases. + For example, when gathering user + input from the console - it's unlikely to be longer than 80. + +

Array Bounds Checking

+ + It is an error to index an array with an index that is less than + 0 or greater than or equal to the array length. If an index is + out of bounds, an ArrayBoundsError exception is raised if detected + at runtime, and an error if detected at compile time. + A program may not rely on array bounds checking happening, for + example, the following program is incorrect: + +
try
+{
+    for (i = 0; ; i++)
+    {
+	array[i] = 5;
+    }
+}
+catch (ArrayBoundsError)
+{
+    // terminate loop
+}
+
+ + The loop is correctly written: + +
for (i = 0; i < array.length; i++)
+{
+    array[i] = 5;
+}
+
+ + Implementation Note: Compilers should attempt to detect + array bounds errors at compile time, for example: + +
int[3] foo;
+int x = foo[3];		// error, out of bounds
+
+ + Insertion of array bounds checking code at runtime should be + turned on and off + with a compile time switch. + +

Array Initialization

+ +

Default Initialization

+ +
    +
  • Pointers are initialized to null. +
  • Static array contents are initialized to the default + initializer for the array element type. +
  • Dynamic arrays are initialized to having 0 elements. +
  • Associative arrays are initialized to having 0 elements. +
+ +

Void Initialization

+ + Void initialization happens when the Initializer for + an array is void. What it means is that no initialization + is done, i.e. the contents of the array will be undefined. + This is most useful as an efficiency optimization. + Void initializations are an advanced technique and should only be used + when profiling indicates that it matters. + +

Static Initialization of Static Arrays

+ +
int[3] a = [ 1:2, 3 ];		// a[0] = 0, a[1] = 2, a[2] = 3
+
+ + This is most handy when the array indices are given by enums: + +
enum Color { red, blue, green };
+
+int value[Color.max + 1] = [ blue:6, green:2, red:5 ];
+
+ + If any members of an array are initialized, they all must be. + This is to catch + common errors where another element is added to an enum, + but one of the static instances + of arrays of that enum was overlooked in updating the + initializer list. + + +

Special Array Types

+ +

Arrays of Bits

+ + Bit vectors can be constructed: + +
bit[10] x;		// array of 10 bits
+
+ + The amount of storage used up is implementation dependent. + Implementation Note: on + Intel CPUs it would be rounded up to the next 32 bit size. + +
x.length		// 10, number of bits
+x.size			// 4,  bytes of storage
+
+ + So, the size per element is not (x.size / x.length). + + + +

Strings

+ + Languages should be good at handling strings. C and C++ are not + good at it. The primary difficulties are memory management, + handling of temporaries, constantly rescanning the string looking + for the terminating 0, and the fixed arrays. +

+ + Dynamic arrays in D suggest the obvious solution - a string is + just a dynamic array of characters. String literals become just + an easy way to write character arrays. + +

char[] str;
+char[] str1 = "abc";
+
+ + char[] strings are in UTF-8 format. + wchar[] strings are in UTF-16 format. + dchar[] strings are in UTF-32 format. +

+ + Strings can be copied, compared, concatenated, and appended: + +

str1 = str2;
+if (str1 < str3) ...
+func(str3 ~ str4);
+str4 ~= str1;
+
+ + with the obvious semantics. Any generated temporaries get cleaned up + by the garbage collector (or by using alloca()). Not only that, + this works with any + array not just a special String array. +

+ + A pointer to a char can be generated: + +

char *p = &amp;str[3];	// pointer to 4th element
+char *p = str;		// pointer to 1st element
+
+ + Since strings, however, are not 0 terminated in D, + when transferring a pointer + to a string to C, add a terminating 0: + +
str ~= "\0";
+
+ + The type of a string is determined by the semantic phase of + compilation. The type is + one of: char[], wchar[], dchar[], and is determined by + implicit conversion rules. + If there are two equally applicable implicit conversions, + the result is an error. To + disambiguate these cases, a cast is appropriate: + +
cast(wchar [])"abc"	// this is an array of wchar characters
+
+ + String literals are implicitly converted between chars, + wchars, and dchars as necessary. +

+ + Strings a single character in length can also be exactly + converted to a char, wchar or dchar constant: + +

char c;
+wchar w;
+dchar d;
+
+c = 'b';		// c is assigned the character 'b'
+w = 'b';		// w is assigned the wchar character 'b'
+w = 'bc';		// error - only one wchar character at a time
+w = "b"[0];		// w is assigned the wchar character 'b'
+w = \r;			// w is assigned the carriage return wchar character
+d = 'd';		// d is assigned the character 'd'
+
+ +

printf() and Strings

+ + printf() is a C function and is not part of D. printf() + will print C strings, which are 0 terminated. There are two ways + to use printf() with D strings. The first is to add a + terminating 0, and cast the result to a char*: + +
str ~= "\0";
+printf("the string is '%s'\n", (char *)str);
+
+ + The second way is to use the precision specifier. The way D arrays + are laid out, the length comes first, so the following works: + +
printf("the string is '%.*s'\n", str);
+
+ + In the future, it may be necessary to just add a new format + specifier to printf() instead of relying on an implementation + dependent detail. + +

Implicit Conversions

+ + A pointer T* can be implicitly converted to + one of the following: + +
    +
  • U* where U is a base class of T. +
  • void* +
+ + A static array T[dim] can be implicitly + converted to + one of the following: + +
    +
  • T* +
  • T[] +
  • U[dim] where U is a base class of T. +
  • U[] where U is a base class of T. +
  • U* where U is a base class of T. +
  • void* +
  • void[] +
+ + A dynamic array T[] can be implicitly converted to + one of the following: + +
    +
  • T* +
  • U[] where U is a base class of T. +
  • U* where U is a base class of T. +
  • void* +
+ + + +
+

Associative Arrays

+ + D goes one step further with arrays - adding associative arrays. + Associative arrays have an index that is not necessarily an integer, + and can be sparsely populated. The index for an associative array + is called the key, and its type is called the KeyType. +

+ + Associative arrays are declared by placing the KeyType + within the [] of an array declaration: + +

int[char[]] b;		// associative array b of ints that are
+			// indexed by an array of characters.
+			// The KeyType is char[]
+b["hello"] = 3;		// set value associated with key "hello" to 3
+func(b["hello"]);	// pass 3 as parameter to func()
+
+ + Particular keys in an associative array can be removed with the + remove function: + +
b.remove("hello");
+
+ + The InExpression yields a pointer to the value + if the key is in the associative array, or null if not: + +
int* p;
+p = ("hello" in b);
+if (p != null)
+	...
+
+ + KeyTypes cannot be functions or voids. +

+ + If the KeyType is a struct type, a default mechanism is used + to compute the hash and comparisons of it based on the binary + data within the struct value. A custom mechanism can be used + by providing the following functions as struct members: + +

uint toHash();
+int opCmp(KeyType* s);
+
+ + For example: + +
import std.string;
+
+struct MyString
+{
+    char[] str;
+
+    uint toHash()
+    {   uint hash;
+	foreach (char c; s)
+	    hash = (hash * 9) + c;
+	return hash;
+    }
+
+    int opCmp(MyString* s)
+    {
+	return std.string.cmp(this.str, s.str);
+    }
+}
+
+ +

Properties

+ +Properties for associative arrays are: + + + + + + + + +
.size + Returns the size of the reference to the associative + array; it is typically 8. + +
.length + Returns number of values in the associative array. + Unlike for dynamic arrays, it is read-only. + +
.keys + Returns dynamic array, the elements of which are the keys in + the associative array. + +
.values + Returns dynamic array, the elements of which are the values in + the associative array. + +
.rehash + Reorganizes the associative array in place so that lookups + are more efficient. rehash is effective when, for example, + the program is done loading up a symbol table and now needs + fast lookups in it. + Returns a reference to the reorganized array. + +
+ +
+

Associative Array Example: word count

+ +
import std.file;		// D file I/O
+
+int main (char[][] args)
+{
+    int word_total;
+    int line_total;
+    int char_total;
+    int[char[]] dictionary;
+
+    printf("   lines   words   bytes file\n");
+    for (int i = 1; i &lt; args.length; ++i)	// program arguments
+    {
+	char[] input;		// input buffer
+	int w_cnt, l_cnt, c_cnt;	// word, line, char counts
+	int inword;
+	int wstart;
+
+	input = std.file.read(args[i]);	// read file into input[]
+
+	foreach (char c; input)
+	{
+	    if (c == '\n')
+		++l_cnt;
+	    if (c >= '0' && c &lt;= '9')
+	    {
+	    }
+	    else if (c >= 'a' && c &lt;= 'z' ||
+		c >= 'A' && c &lt;= 'Z')
+	    {
+		if (!inword)
+		{
+		    wstart = j;
+		    inword = 1;
+		    ++w_cnt;
+		}
+	    }
+	    else if (inword)
+	    {   char[] word = input[wstart .. j];
+
+		dictionary[word]++;		// increment count for word
+		inword = 0;
+	    }
+	    ++c_cnt;
+	}
+	if (inword)
+	{   char[] word = input[wstart .. input.length];
+	    dictionary[word]++;
+	}
+	printf("%8ld%8ld%8ld %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
+	line_total += l_cnt;
+	word_total += w_cnt;
+	char_total += c_cnt;
+    }
+
+    if (args.length > 2)
+    {
+	printf("-------------------------------------\n%8ld%8ld%8ld total",
+	    line_total, word_total, char_total);
+    }
+
+    printf("-------------------------------------\n");
+    char[][] keys = dictionary.keys;	// find all words in dictionary[]
+    for (int i = 0; i &lt; keys.length; i++)
+    {   char[] word;
+
+	word = keys[i];
+	printf("%3d %.*s\n", dictionary[word], word);
+    }
+    return 0;
+}
+
+ + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/attribute.html dmd-0.136/dmd/html/d/attribute.html --- dmd-0.135/dmd/html/d/attribute.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/attribute.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,576 +1,624 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Attributes - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - -

Attributes

- -
-	AttributeSpecifier:
-	    Attribute :
-	    Attribute DeclDefBlock
-	    Pragma ;
-
-	AttributeElseSpecifier:
-	    AttributeElse :
-	    AttributeElse DeclDefBlock
-	    AttributeElse DeclDefBlock else DeclDefBlock
-
-	Attribute:
-	    LinkageAttribute
-	    AlignAttribute
-	    Pragma
-	    deprecated
-	    private
-	    package
-	    protected
-	    public
-	    export
-	    static
-	    final
-	    override
-	    abstract
-	    const
-	    auto
-
-	AttributeElse:
-	    DebugAttribute
-	    VersionAttribute
-
-	DeclDefBlock
-	    DeclDef
-	    { }
-	    { DeclDefs }
-	
- - Attributes are a way to modify one or more declarations. - The general forms are: - -
-	attribute declaration;		affects the declaration
-
-	attribute:			affects all declarations until the next }
-	    declaration;
-	    declaration;
-	    ...
-
-	attribute			affects all declarations in the block
-	{
-	    declaration;
-	    declaration;
-	    ...
-	}
-	
- - For attributes with an optional else clause: - -
-	attribute
-	    declaration;
-	else
-	    declaration;
-
-	attribute			affects all declarations in the block
-	{
-	    declaration;
-	    declaration;
-	    ...
-	}
-	else
-	{
-	    declaration;
-	    declaration;
-	    ...
-	}
-	
- -

Linkage Attribute

- -
-	LinkageAttribute:
-		extern
-		extern ( LinkageType )
-
-	LinkageType:
-		C
-		C++
-		D
-		Windows
-		Pascal
-	
- - D provides an easy way to call C functions and operating - system API functions, as compatibility with both is essential. - The LinkageType is case sensitive, and is meant to be - extensible by the implementation (they are not keywords). - C and D must be supplied, the others are what - makes sense for the implementation. - C++ is reserved for future use. - Implementation Note: - for Win32 platforms, Windows and Pascal should exist. -

- - C function calling conventions are - specified by: - -

-	extern (C):
-		int foo();	call foo() with C conventions
-	
- - D conventions are: - -
-	extern (D):
-	
- - or: - -
-	extern:
-	
- - - Windows API conventions are: - -
-	extern (Windows):
-	    void *VirtualAlloc(
-	    void *lpAddress,
-	    uint dwSize,
-	    uint flAllocationType,
-	    uint flProtect
-	    );
-	
- -

Align Attribute

- -
-	AlignAttribute:
-		align
-		align ( Integer )
-	
- - Specifies the alignment of struct members. align by itself - sets it to the default, which matches the default member alignment - of the companion C compiler. Integer specifies the alignment - which matches the behavior of the companion C compiler when non-default - alignments are used. -

- - Matching the behavior of the companion C compiler can have some - surprising results, such as the following for Digital Mars C++: - -

-	struct S
-	{   align(4) byte a;	// placed at offset 0
-	    align(4) byte b;	// placed at offset 1
-	}
- - AlignAttribute is meant for C ABI compatiblity, which is not - the same thing as binary compatibility across diverse platforms. - For that, use packed structs: - -
-	align (1) struct S
-	{   byte a;	// placed at offset 0
-	    byte[3] filler1;
-	    byte b;	// placed at offset 4
-	    byte[3] filler2;
-	}
- - A value of 1 means that no alignment is done; - members are packed together. -

- - Do not align references or pointers that were allocated - using NewExpression on boundaries that are not - a multipe of 4. The garbage collector assumes that pointers - and references to gc allocated objects will be on 4 - byte boundaries. If they are not, undefined behavior will - result. -

- - AlignAttribute is ignored when applied to declarations - that are not structs or struct members. - -

Deprecated Attribute

- - It is often necessary to deprecate a feature in a library, - yet retain it for backwards compatibility. Such - declarations can be marked as deprecated, which means - that the compiler can be set to produce an error - if any code refers to deprecated - declarations: - -
-	deprecated
-	{
-		void oldFoo();
-	}
-	
- - Implementation Note: The compiler should have a switch - specifying if deprecated declarations should be compiled with - out complaint or not. - - -

Protection Attribute

- - Protection is an attribute that is one of - private, package, protected, - public or export. -

- - Private means that only members of the enclosing class can access - the member, or members and functions in the same module as the - enclosing class. - Private members cannot be overridden. - Private module members are equivalent to static declarations - in C programs. -

- - Package extends private so that package members can be accessed - from code in other modules that are in the same package. - This applies to the innermost package only, if a module is in - nested packages. -

- - Protected means that only members of the enclosing class or any - classes derived - from that class, or members and functions in the same module - as the enclosing class, can access the member. - Protected module members are illegal. -

- - Public means that any code within the executable can access the member. -

- - Export means that any code outside the executable can access the - member. Export - is analogous to exporting definitions from a DLL. - -

Const Attribute

- -
-	const
-	
- - The const attribute declares constants that can be - evaluated at compile time. For example: - -
-	const int foo = 7;
-
-	const
-	{
-	    double bar = foo + 6;
-	}
-	
- - A const declaration without an initializer must be initialized - in a constructor (for class fields) or in a static constructor - (for static class members, or module variable declarations). - -
-	const int x;
-	const int y;
-
-	static this()
-	{
-	    x = 3;	// ok
-	    // error: y not initialized
-	}
-
-	void foo()
-	{
-	    x = 4;	// error, x is const and not in static constructor
-	}
-
-	class C
-	{
-	    const int a;
-	    const int b;
-	    static const int c;
-	    static const int d;
-
-	    this()
-	    {	a = 3;		// ok
-		a = 4;		// ok, multiple initialization allowed
-		C p = this;
-		p.a = 4;	// error, only members of this instance
-		c = 5;		// error, should initialize in static constructor
-		// error, b is not initialized
-	    }
-
-	    this(int x);
-	    {
-		this();		// ok, forwarding constructor
-	    }
-
-	    static this()
-	    {
-		c = 3;		// ok
-		// error, d is not initialized
-	    }
-	}
-	
- - It is not an error to have const module variable declarations without - initializers if there is no constructor. This is to support the practice - of having modules serve only as declarations that are not linked in, - the implementation of it will be in another module that is linked in. - - -

Override Attribute

- -
-	override
-	
- - The override attribute applies to virtual functions. - It means that the function must override a function with the - same name and parameters in a base class. The override attribute - is useful for catching errors when a base class's member function - gets its parameters changed, and all derived classes need to have - their overriding functions updated. - -
-	class Foo
-	{
-	    int bar();
-	    int abc(int x);
-	}
-
-	class Foo2 : Foo
-	{
-	    override
-	    {
-		int bar(char c);	// error, no bar(char) in Foo
-		int abc(int x);		// ok
-	    }
-	}
-	
- -

Static Attribute

- -
-	static
-	
- - The static attribute applies to functions and data. - It means that the declaration does not apply to a particular - instance of an object, but to the type of the object. In - other words, it means there is no this reference. - static is ignored when applied to other declarations. - -
-	class Foo
-	{
-	    static int bar() { return 6; }
-	    int foobar() { return 7; }
-	}
-
-	...
-
-	Foo f = new Foo;
-	Foo.bar();	// produces 6
-	Foo.foobar();	// error, no instance of Foo
-	f.bar();	// produces 6;
-	f.foobar();	// produces 7;
-	
- - Static functions are never virtual. -

- - Static data has only one instance for the entire program, - not once per object. -

- - Static does not have the additional C meaning of being local - to a file. Use the private attribute in D to achieve that. - For example: - -

-	module foo;
-	int x = 3;		// x is global
-	private int y = 4;	// y is local to module foo
-	
- - -

Auto Attribute

- -
-	auto
-	
- - The auto attribute is used for local variables and for class - declarations. For class declarations, the auto attribute creates - an auto class. - For local declarations, auto implements the RAII (Resource - Acquisition Is Initialization) protocol. This means that the - destructor for an object is automatically called when the auto - reference to it goes out of scope. The destructor is called even - if the scope is exited via a thrown exception, thus auto - is used to guarantee cleanup. -

- - If there is more than one auto variable going out of scope - at the same point, then the destructors are called in the reverse - order that the variables were constructed. -

- - Auto cannot be applied to globals, statics, data members, inout - or out parameters. Arrays of autos are not allowed, and auto - function return values are not allowed. Assignment to an auto, - other than initialization, is not allowed. - Rationale: These restrictions may get relaxed in the future - if a compelling reason to appears. - - -

Abstract Attribute

- - If a class is abstract, it cannot be instantiated - directly. It can only be instantiated as a base class of - another, non-abstract, class. -

- - Classes become abstract if they are defined within an - abstract attribute, or if any of the virtual member functions - within it are declared as abstract. -

- - Non-virtual functions cannot be declared as abstract. -

- - Functions declared as abstract can still have function - bodies. This is so that even though they must be overridden, - they can still provide 'base class functionality.' - - -

-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Attributes + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ +

Attributes

+ +
+AttributeSpecifier:
+    Attribute :
+    Attribute DeclDefBlock
+    Pragma ;
+
+AttributeElseSpecifier:
+    AttributeElse :
+    AttributeElse DeclDefBlock
+    AttributeElse DeclDefBlock else DeclDefBlock
+
+Attribute:
+    LinkageAttribute
+    AlignAttribute
+    Pragma
+    deprecated
+    private
+    package
+    protected
+    public
+    export
+    static
+    final
+    override
+    abstract
+    const
+    auto
+
+AttributeElse:
+    DebugAttribute
+    VersionAttribute
+
+DeclDefBlock
+    DeclDef
+    { }
+    { DeclDefs }
+
+ + + Attributes are a way to modify one or more declarations. + The general forms are: + +
+attribute declaration;		affects the declaration
+
+attribute:			affects all declarations until the next }
+    declaration;
+    declaration;
+    ...
+
+attribute			affects all declarations in the block
+{
+    declaration;
+    declaration;
+    ...
+}
+
+ + For attributes with an optional else clause: + +
+attribute
+    declaration;
+else
+    declaration;
+
+attribute			affects all declarations in the block
+{
+    declaration;
+    declaration;
+    ...
+}
+else
+{
+    declaration;
+    declaration;
+    ...
+}
+
+ +

Linkage Attribute

+ +
+LinkageAttribute:
+	extern
+	extern ( LinkageType )
+
+LinkageType:
+	C
+	C++
+	D
+	Windows
+	Pascal
+
+ + + D provides an easy way to call C functions and operating + system API functions, as compatibility with both is essential. + The LinkageType is case sensitive, and is meant to be + extensible by the implementation (they are not keywords). + C and D must be supplied, the others are what + makes sense for the implementation. + C++ is reserved for future use. + Implementation Note: + for Win32 platforms, Windows and Pascal should exist. +

+ + C function calling conventions are + specified by: + +

extern (C):
+	int foo();	// call foo() with C conventions
+
+ + D conventions are: + +
extern (D):
+
+ + or: + +
extern:
+
+ + + Windows API conventions are: + +
extern (Windows):
+    void *VirtualAlloc(
+    void *lpAddress,
+    uint dwSize,
+    uint flAllocationType,
+    uint flProtect
+    );
+
+ +

Align Attribute

+ +
+AlignAttribute:
+	align
+	align ( Integer )
+
+ + + Specifies the alignment of struct members. align by itself + sets it to the default, which matches the default member alignment + of the companion C compiler. Integer specifies the alignment + which matches the behavior of the companion C compiler when non-default + alignments are used. +

+ + Matching the behavior of the companion C compiler can have some + surprising results, such as the following for Digital Mars C++: + +

struct S
+{   align(4) byte a;	// placed at offset 0
+    align(4) byte b;	// placed at offset 1
+}
+
+ + AlignAttribute is meant for C ABI compatiblity, which is not + the same thing as binary compatibility across diverse platforms. + For that, use packed structs: + +
align (1) struct S
+{   byte a;	// placed at offset 0
+    byte[3] filler1;
+    byte b;	// placed at offset 4
+    byte[3] filler2;
+}
+
+ + A value of 1 means that no alignment is done; + members are packed together. +

+ + Do not align references or pointers that were allocated + using NewExpression on boundaries that are not + a multipe of 4. The garbage collector assumes that pointers + and references to gc allocated objects will be on 4 + byte boundaries. If they are not, undefined behavior will + result. +

+ + AlignAttribute is ignored when applied to declarations + that are not structs or struct members. + +

Deprecated Attribute

+ + It is often necessary to deprecate a feature in a library, + yet retain it for backwards compatibility. Such + declarations can be marked as deprecated, which means + that the compiler can be set to produce an error + if any code refers to deprecated + declarations: + +
deprecated
+{
+	void oldFoo();
+}
+
+ + Implementation Note: The compiler should have a switch + specifying if deprecated declarations should be compiled with + out complaint or not. + + +

Protection Attribute

+ + Protection is an attribute that is one of + private, package, protected, + public or export. +

+ + Private means that only members of the enclosing class can access + the member, or members and functions in the same module as the + enclosing class. + Private members cannot be overridden. + Private module members are equivalent to static declarations + in C programs. +

+ + Package extends private so that package members can be accessed + from code in other modules that are in the same package. + This applies to the innermost package only, if a module is in + nested packages. +

+ + Protected means that only members of the enclosing class or any + classes derived + from that class, or members and functions in the same module + as the enclosing class, can access the member. + Protected module members are illegal. +

+ + Public means that any code within the executable can access the member. +

+ + Export means that any code outside the executable can access the + member. Export + is analogous to exporting definitions from a DLL. + +

Const Attribute

+ +
+const
+
+ + + The const attribute declares constants that can be + evaluated at compile time. For example: + +
const int foo = 7;
+
+const
+{
+    double bar = foo + 6;
+}
+
+ + A const declaration without an initializer must be initialized + in a constructor (for class fields) or in a static constructor + (for static class members, or module variable declarations). + +
const int x;
+const int y;
+
+static this()
+{
+    x = 3;	// ok
+    // error: y not initialized
+}
+
+void foo()
+{
+    x = 4;	// error, x is const and not in static constructor
+}
+
+class C
+{
+    const int a;
+    const int b;
+    static const int c;
+    static const int d;
+
+    this()
+    {   a = 3;		// ok
+	a = 4;		// ok, multiple initialization allowed
+	C p = this;
+	p.a = 4;	// error, only members of this instance
+	c = 5;		// error, should initialize in static constructor
+	// error, b is not initialized
+    }
+
+    this(int x);
+    {
+	this();		// ok, forwarding constructor
+    }
+
+    static this()
+    {
+	c = 3;		// ok
+	// error, d is not initialized
+    }
+}
+
+ + It is not an error to have const module variable declarations without + initializers if there is no constructor. This is to support the practice + of having modules serve only as declarations that are not linked in, + the implementation of it will be in another module that is linked in. + + +

Override Attribute

+ +
+override
+
+ + + The override attribute applies to virtual functions. + It means that the function must override a function with the + same name and parameters in a base class. The override attribute + is useful for catching errors when a base class's member function + gets its parameters changed, and all derived classes need to have + their overriding functions updated. + +
class Foo
+{
+    int bar();
+    int abc(int x);
+}
+
+class Foo2 : Foo
+{
+    override
+    {
+	int bar(char c);	// error, no bar(char) in Foo
+	int abc(int x);		// ok
+    }
+}
+
+ +

Static Attribute

+ +
+static
+
+ + + The static attribute applies to functions and data. + It means that the declaration does not apply to a particular + instance of an object, but to the type of the object. In + other words, it means there is no this reference. + static is ignored when applied to other declarations. + +
class Foo
+{
+    static int bar() { return 6; }
+    int foobar() { return 7; }
+}
+
+...
+
+Foo f = new Foo;
+Foo.bar();	// produces 6
+Foo.foobar();	// error, no instance of Foo
+f.bar();	// produces 6;
+f.foobar();	// produces 7;
+
+ + Static functions are never virtual. +

+ + Static data has only one instance for the entire program, + not once per object. +

+ + Static does not have the additional C meaning of being local + to a file. Use the private attribute in D to achieve that. + For example: + +

module foo;
+int x = 3;		// x is global
+private int y = 4;	// y is local to module foo
+
+ + +

Auto Attribute

+ +
+auto
+
+ + + The auto attribute is used for local variables and for class + declarations. For class declarations, the auto attribute creates + an auto class. + For local declarations, auto implements the RAII (Resource + Acquisition Is Initialization) protocol. This means that the + destructor for an object is automatically called when the auto + reference to it goes out of scope. The destructor is called even + if the scope is exited via a thrown exception, thus auto + is used to guarantee cleanup. +

+ + If there is more than one auto variable going out of scope + at the same point, then the destructors are called in the reverse + order that the variables were constructed. +

+ + Auto cannot be applied to globals, statics, data members, inout + or out parameters. Arrays of autos are not allowed, and auto + function return values are not allowed. Assignment to an auto, + other than initialization, is not allowed. + Rationale: These restrictions may get relaxed in the future + if a compelling reason to appears. + + +

Abstract Attribute

+ + If a class is abstract, it cannot be instantiated + directly. It can only be instantiated as a base class of + another, non-abstract, class. +

+ + Classes become abstract if they are defined within an + abstract attribute, or if any of the virtual member functions + within it are declared as abstract. +

+ + Non-virtual functions cannot be declared as abstract. +

+ + Functions declared as abstract can still have function + bodies. This is so that even though they must be overridden, + they can still provide 'base class functionality.' + + + +

+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/changelog.html dmd-0.136/dmd/html/d/changelog.html --- dmd-0.135/dmd/html/d/changelog.html 2005-09-28 16:44:18.000000000 +0200 +++ dmd-0.136/dmd/html/d/changelog.html 2005-10-17 00:39:32.000000000 +0200 @@ -1,2580 +1,2776 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Change Log - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Wed Sep 28 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - - -

D Change Log

- - - - -
-

- What's New for - D 0.134 -

- -Sep 28, 2005 -

- -

New/Changed Features

-
    -
- -

Ddoc

-
    -
  • Added $1 .. $9 macro arguments, and $+ special macro. -
  • Each standard section now has its own custom DDOC_ macro. -
  • Incorporated Bob W's suggestions
  • . -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.133 -

- -Sep 24, 2005 -

- -

New/Changed Features

-
    -
  • Filled out std.math with standard C math.h functions. -
  • Added -o- flag to suppress generation of object file. -
- -

Ddoc

-
    -
  • Removes closing *'s on /******* Comment ***********/ -
  • '_' in section names now replaced with ' ' (Derek Parnell's idea). -
  • Extensive revision to how macros work based on a - suggestion from Derek Parnell. Much more flexible now. -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.132 -

- -Sep 19, 2005 -

- -

New/Changed Features

-
    -
  • Added Ddoc, the documentation - generator for D.
  • -
- - -
-

- What's New for - D 0.131 -

- -Sep 8, 2005 -

- -

New/Changed Features

-
    -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.130 -

- -Sep 6, 2005 -

- -

New/Changed Features

-
    -
  • Added Don Clugston's std.math.feqrel(). -
  • Added Ben Hinkle's updates to std.stream: - - -
  • Added Ben Hinkle's updates to std.mmfile from thread - D.bugs/4550
  • -
      -
    • added windowing support -
    • changed size parameters to ulong instead of size_t -
    • commented out the debug printf -
    • added unittests -
    • updated help -
    - -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.129 -

- -Aug 5, 2005 -

- -

New/Changed Features

-
    -
  • Added postfixes c, w, d to string literals to denote type. -
  • -
  • For linux, DW_LANG_D is used for DW_AT_language in the Dwarf - symbolic debug info. If the - -gc switch is used, DW_LANG_C is used for older GDB's. -
  • -
  • Incorporated Ben Hinkle's new std.format which can print - general arrays. -
  • -
  • Added std.stdio.writefx and std.stream.writefx - from David L. Davis and Ben Hinkle. -
  • Incorporated Ameer Armaly's improvement to std.c.linux.linux.
  • -
- -

Bugs Fixed

-
    -
  • Implemented access checking for structs.
  • -
  • Fixed D.bugs/4555
  • -
- -
-

- What's New for - D 0.128 -

- -Jul 10, 2005 -

- -

New/Changed Features

- - -

Bugs Fixed

- - -
-

- What's New for - D 0.127 -

- -Jun 16, 2005 -

- -

New/Changed Features

-
    -
  • No more forward references of version or debug identifiers.
  • -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.126 -

- -Jun 7, 2005 -

- -

New/Changed Features

-
    -
  • === now deprecated, replaced with is. -
  • !== now deprecated, replaced with !is. -
  • Added typesafe variadic functions. -
  • Now throws an ArrayBoundsError if accessing an associative - array with a key that is not already in the array. Previously, - the key would be added to the array. -
  • Added IsExpressions - which replace IftypeConditions - which are now deprecated. - The IsExpressions are significantly - more general and powerful. -
  • Added VoidInitializers. -
  • delete aa[key] is now deprecated, use - aa.remove(key) instead. -
  • Added non-static nested classes. -
  • Added anonymous non-static nested - classes. -
  • Incorporated Ben Hinkle's changes to std.stream: -
      -
    • std.stream.stdin/out/err deprecated -
    • adding std.cstream.din/out/err -
    • stream.d: -
        -
      • incorporate the socketstream code for handling \r - end-of-line formats for readLine on non-seekable streams like - pipes -
      • getc and getcw return char.init and wchar.init on EOF -
      • getcw throws if EOF after reading 1 byte -
      • ungetc and ungetcw ignore char.init and wchar.init -
      • deprecate stdin,stdout,stderr -
      • remove private import of std.c.stdio and aliases for - va_list -
      -
    • -
    • socketstream.d: removed overrides that are now in std.stream.Stream -
    • cstream.d: new stream wrapper around FILE* with din, dout, derr -
    • unittest,d: add cstream to ensure unittests are run -
    -
  • -
- -

Bugs Fixed

-
    -
  • Fixed Internal error: e2ir.c 488 -
  • Incorporated David Friedman's patch for std.base64. -
  • Fixed D.bugs/4178 -
  • Incorporated evilmrhenry's fixes from D.bugs/4215 -
  • Fixed std.math.tan's bug where it could leave an operand on the FPU - stack -
- -
-

- What's New for - D 0.125 -

- -May 20, 2005 -

- -

New/Changed Features

-
    -
- -

Bugs Fixed

-
    -
  • iftype fixed to do implicit conversion match with - specialization, rather than exact match. -
  • Fixed D.bugs/4075 -
  • Ben Hinkle fixed D.learn/873 -
  • phobos/internal/gc _d_newarrayi() fixed to use std.c.stdarg. -
- -
-

- What's New for - D 0.124 -

- -May 19, 2005 -

- -

New/Changed Features

-
    -
  • Added -quiet switch to dmd. -
  • .size property is no longer deprecated, it is - an error. Replace with .sizeof. -
  • Renamed DMD source debcond.h to cond.h, debcond.c to cond.c. -
  • Added Burton Radons' std.boxer. -
  • Reformatted the documentation to use a bit of color. -
  • Added static if. -
  • Added iftype. -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.123 -

- -May 11, 2005 -

- -

New/Changed Features

-
    -
  • Capped static array size at 16Mb. -
- -

Bugs Fixed

- - -
-

- What's New for - D 0.122 -

- -May 3, 2005 -

- -

New/Changed Features

-
    -
  • Added Ben Hinkle's fixes for std.stream: -
      -
    • fixes the seekable bugs on reading stdin and pipes -
    • adds isOpen and eof to InputStream -
    • adds isOpen, flush and close to OutputStream -
    -
  • Added std.conv.toFloat, toDouble, toReal from David L. Davis. -
- -

Bugs Fixed

-
    -
  • Improved line numbers in error messages. -
  • Fixed problems detecting array overflows at compile time. -
  • Improved handling of compiler out-of-memory errors. -
  • Fixed DMDScript build break. -
  • Fixed memory corruption problem with array[length..length]. -
  • Fixed compiler seg fault on uplevel invariant. -
  • Fixed problem detecting circular interface hierarchies. -
  • Fixed cat of static arrays. -
  • Fixed Internal error cg87 1240. -
  • Fixed D.bugs/3710 -
  • Fixed D.bugs/3747 -
  • Fixed D.bugs/3752 -
  • Fixed D.bugs/3753 -
- -
-

- What's New for - D 0.121 -

- -Apr 15, 2005 -

- -

New/Changed Features

-
    -
  • std.syserror is now deprecated, replaced with - std.windows.syserror. It is Windows specific, and - lining it up with strerror() on Linux was a mistake. Windows - error numbers do not line up with C's errno values. - Thanks to Regan Heath for a decent implementation of it. -
  • Now ?: works with null and arrays. -
  • Changed std.outofmemory.OutOfMemory to - std.outofmemory.OutOfMemoryException, and it now - derives from Exception. -
  • Abstract class methods now cause the class to be abstract. -
  • Abstract can no longer be applied to variables, structs - or unions. -
  • Unit tests now allowed in structs and unions. -
- -

Bugs Fixed

-
    -
  • Added zwang's fix for std.string.ifind(). -
  • Fixed constant fold divide by 0. -
  • Fixed "Win32 Exception" in std.regexp. -
  • Fixed bogus "switch statement already has a default" bug. -
  • Fixed D.bugs/2991 -
  • Fixed D.bugs/3002 -
  • Fixed D.bugs/3034 -
  • Fixed D.bugs/3091 -
  • Fixed D.bugs/3129 -
  • Fixed D.bugs/3551 -
  • Fixed D.bugs/3597 -
  • Fixed D.bugs/3646 -
  • Implemented typeinfo's for arrays, static arrays, associative - arrays, function pointers, delegates, and enums. -
  • Fixed typeinfo for typedef's. -
  • Fixed broken implicit conversion from real or imaginary - to complex. -
  • Fixed pragma error messages. -
  • Fixed broken pragma(lib) inside function. -
  • Fixed dstress slice_10. -
  • Fixed dstress argument_03. -
  • Fixed dstress const_04. -
  • Fixed dstress foreach_26. -
  • Fixed dstress html_empty_entity_03. -
  • Fixed dstress invariant_12. -
  • Fixed dstress invariant_29, _30, _31. -
  • Fixed dstress main_06. -
  • Fixed dstress mixin_09. -
  • Fixed dstress new_09. -
  • Incorporated Ben Hinkle's fixes for std.stream. Fixed a bug - introduced in dmd-120: - D.bugs/3563 - about seekable stdin and Stream.toString(). Fixed a bug in - the Windows version of seek() with files larger than uint.sizeof. - -
- -
-

- What's New for - D 0.120 -

- -Apr 6, 2005 -

- -

New/Changed Features

-
    -
  • In -release builds implicit switch defaults, - implicit return statements, and assert(0) expressions are - replaced with HLT instructions. -
  • Renamed -gt command line switch that invokes the profiler - to -profile. -
  • Complex types can no longer be implicitly converted to - non-complex types. -
  • Real and imaginary types can no longer be implicitly converted - to each other. -
  • Added Pentium 4 (Prescott) instructions to inline assembler. -
  • Template alias parameters can now have specializations. -
  • Compiler now permitted to retain floating point literals - and do constant folding on them in a precision that is greater - than the precision of its type. -
  • Changed AMD64 predefined version to X86_64. -
  • Added Matthew Wilson's std.openrj. -
  • Ben Hinkle submitted a new std.stream - with: - -
    -
      -
    • replace uint buffer lengths with size_t -
    • add line-by-line opApply to Stream and InputStream (due to Regan - Heath)
      - int opApply(int delegate(inout char[] line) dg)
      - int opApply(int delegate(inout ulong n, inout char[] line) dg)
      - int opApply(int delegate(inout wchar[] line) dg)
      - int opApply(int delegate(inout ulong n, inout wchar[] line) dg) -
    • move readable/writeable/seekable tests from contracts to the body - since phobos is compiled in release mode and users can easily try - to write to an unwritable stream -
    • return "this" from writef and writefln to allow chaining (eg flush) -
    • fix TArrayStream read/write to check for "eof" (Derick Eddington) -
    • make SliceStream preserve the source buffer position if seekable - and pay attention to isOpen (Derick) -
    • implement available() for more stream types (Derick) -
    • copyFrom bug fixes and position preserving if seekable (Derick) -
    • move the initialization of the BOMs to the initializer instead of the - module constructor. -
    • make isopen protected (from private) so that subclasses can see it. -
    • more unittest (Derick and Ben) -
    • fix File.size() bug on Windows -
    • fix File.open() error message to say "Cannot open or create file" -
    -
    -
- -

Bugs Fixed

-
    -
  • Fixed crash with forward reference of local as mixin alias - parameter. -
  • Fixed bit array append. -
  • Fixed base class fwd ref bug introduced in 0.119. -
  • Fixed problems with throwing in a destructor. -
  • Fixed problem with misaligned arrays of structs. -
  • Fixed diagnosis of types based on deprecated symbols. -
  • Fixed bad code gen for PEXTRW instruction. -
  • Fixed compiler hang with template alias parameters. -
  • Fixed Internal error: ..\ztc\cg87.c 279 -
  • Fixed Internal error: ..\ztc\cod1.c 1648 -
  • Fixed Internal error: ..\ztc\cgobj.c 2139 -
  • Fixed Internal error: ..\ztc\cgcs.c 353 -
  • Fixed Assertion failure 622 glue.c -
  • Fixed compiler crash on circular typedef declarations. -
  • Fixed compiler crash on empty catch handlers. -
  • Fixed D.bugs/2606 -
  • Fixed D.bugs/2618 -
  • Fixed D.bugs/3234 -
  • Fixed D.bugs/3369 -
- -
-

- What's New for - D 0.119 -

- -Mar 18, 2005 -

- -

New/Changed Features

-
    -
  • Clarified and revamped handling of 'finally' blocks. -
  • C-style casts are no longer deprecated, they are now illegal. -
  • Invalid UTF sequences in comments are now diagnosed as errors. -
  • Can no longer set predefined versions. -
- -

Bugs Fixed

-
    -
  • Fixed &lsaquo; misspelled entity. -
  • Fixed parsing entities with digits. -
  • Class invariant calls no longer attached to private, protected, - or package member functions. -
  • Fixed D.bugs/32 -
  • Fixed D.bugs/1148 -
  • Fixed D.bugs/1815 -
  • Fixed D.bugs/1865 -
  • Fixed D.bugs/1953 -
  • Fixed D.bugs/2042 -
  • Fixed D.bugs/2140 -
  • Fixed D.bugs/2240 -
  • Fixed D.bugs/2262 -
  • Fixed D.bugs/2429 -
  • Fixed D.bugs/2546 -
  • Fixed D.bugs/2934 -
  • Changed documentation on struct/union grammar to allow - invariants, unit tests, and allocator/deallocators. -
  • The file names printed out by runtime assert failures now matches - what was set by any preceding #line LineNumber FileName. -
  • Fixed bug with aliases as struct members. -
  • Error now diagnosed when override is applied to non- - class member functions. -
  • Fixed colliding template struct initializer problem under Linux. -
  • Can now cat string literals to wchar[] or dchar[]. -
  • Now correctly diagnoses as an error attempts to access - members of outer aggregate from within inner aggregate. -
  • Fixed Assertion failure: 'cd' on line 1275 in file 'expression.c' -
  • Now diagnoses error when catches are 'hidden' by previous - catch parameters. -
  • Added missing typeid's for void, void[] and bit[]. -
- -
-

- What's New for - D 0.118 -

- -Mar 12, 2005 -

- -

Bugs Fixed

-
    -
  • Fixed introduced name mangling bug. -
  • Fixed introduced bug with COMDAT records. -
- -
-

- What's New for - D 0.117 -

- -Mar 10, 2005 -

- -

New/Changed Features

-
    -
  • Added pragma(lib, "library name"); -
  • cent and ucent are now keywords, to ensure - they stay reserved. -
  • version=all cannot be explicitly set; - all is always on anyway. -
- -

Bugs Fixed

-
    -
  • Fixed spurious unreachable code warning. -
  • Now issues error for declaring non-virtual functions as abstract. -
  • Declaring an entire class as abstract now works. -
  • Added wprintf back to std.c.stdio. -
  • Instantiating deprecated classes now generates deprecation message. -
  • Fixed several cases where deprecated symbol uses were not flagged. -
  • Can now goto case into enclosing switch case. -
  • Fixed problem with goto into if(0) block. -
  • Incorporated Stewart Gordon's fix for std.file.copy(). -
  • Fixed Assertion failure: '0' on line 720 in file 'statement.c' -
  • Fixed D.bugs/1795 -
  • Fixed D.bugs/2737 -
  • Fixed D.bugs/752 -
  • Fixed D.bugs/1326 -
  • Fixed D.bugs/2238 -
  • Fixed D.bugs/2275 -
  • Fixed D.bugs/2315 -
  • Fixed D.bugs/2316 -
- -
-

- What's New for - D 0.116 -

- -Mar 7, 2005 -

- -

New/Changed Features

-
    -
  • Added named character entities - to escape sequences. -
  • Added much better named character entity - support to HTML preprocessing. -
  • Added __FILE__, __LINE__, __DATE__, __TIME__, __TIMESTAMP__. -
  • $ can now be used instead of length inside an array's - []. It represents the length of the array. This is a trial feature, - if it works out then these will happen in sequential releases: -
      -
    1. length will become deprecated inside []. -
    2. length will be removed as the implicitly declared length, - and it will be just another identifier. -
    -
  • Added warnings on a trial basis. -
  • If a module statement name is used with a package prefix, as in: -
    -	module foo.bar;
    - then bar is not in scope, one must use foo.bar. -
- -

Bugs Fixed

-
    -
  • Fixed several errors in HTML preprocessing - entities, - line numbers, spaces, casing. -
  • Fixed mac line termination. -
  • Fixed D.gnu/983 bug -
  • Fixed D.bugs/1849 -
  • Added missing typeid's for arrays of floating point types. -
  • .sort property now works on arrays of bits and NaNs. -
  • Can now return an expression from a function returning void. -
  • Can have a main() as a nested function. -
- -
-

- What's New for - D 0.115 -

- -Feb 28, 2005 -

- -

Bugs Fixed

-
    -
  • Fixed my bungled integration of std.socket. -
- -
-

- What's New for - D 0.114 -

- -Feb 27, 2005 -

- -

New/Changed Features

-
    -
  • Renamed std.regexp.RegExp.search to - std.regexp.RegExp.find - to be analogous to names in - std.string. Old name remains as - a deprecated alias. -
  • Added functions split, find, rfind, - sub, search to - std.regexp. -
  • Added functions tr, - succ, squeeze, removechars, countchars, - inPattern, chop, - and chomp to std.string. -
  • Incorporated Christopher E. Miller's fixes to std.socket: - -
    - IPv6 not supported but the C interface for it should all be there. - Split up socket.d and put the C stuff in std.c modules. - std.c.linux.linux updated because most of the socket functions - are actually regular I/O functions. Added classes Protocol and Service. - Added Socket.accepting() to allow derived classes to be - accepted. - Documentation and samples updated. - Fixed major bug in the linux version. -
    - -
  • Improved error message for overloaded function mismatches. -
  • Added man pages to \dmd\man\man1 (thanks to Anders F Bjorklund) -
- -

Bugs Fixed

-
    -
  • Fixed std.format %A unittest failure under linux -
  • Fixed proxy static constructor ordering problem. -
  • Fixed bug where v.init would initialize v. -
  • Fixed .reverse bug of char[] and wchar[] with multibyte encodings. -
  • Fixed various problems with constant folding for const initializers. -
  • Fixed Internal error: ../ztc/cod4.c 352 -
  • Fixed Assertion failure: 'ta' on line 1481 in file 'template.c' -
  • Fixed Assertion failure: 'f' on line 3005 in file 'expression.c' -
  • Fixed Assertion failure: 'ids->vthis' on line 394 in file 'inline.c' -
  • Fixed Assertion failure: '0' on line 909 in file 'func.c' -
  • Fixed Assertion failure: '!scopesym || !scopesym->isWithScopeSymbol()' on line 2637 in - file 'mtype.c' -
  • Fixed Assertion failure: 'se2->op == TOKstring' on line 1379 in file 'expression.c' -
  • Fixed Assertion failure: '!needThis()' on line 139 in file 'tocsym.c' -
- -
-

- What's New for - D 0.113 -

- -Feb 12, 2005 -

- -

New/Changed Features

-
    -
  • internal/qsort2.d is now a freely redistributable version of - internal/qsort.d. -
  • Added std.file.copy -
  • Asserts enabled in release builds if -unittest is given. -
- -

Bugs Fixed

-
    -
  • Fixed cgcs 353 error -
  • Fixed dmd crash on class C{this(){super();}} -
  • Fixed dmd crash on cast(int)(.0>>0) -
  • Fixed dmd crash on enum e; -
  • Fixed dmd crash on 0==Exception; -
  • Fixed dmd crash on varargs in initializer -
  • Fixed dmd crash on labeled {} statements -
  • Fixed dmd crash on mishandled forward reference -
  • Fixed Internal error: e2ir.c 229 -
  • Fixed Internal error: ..\ztc\cgcod.c 1640 -
  • Fixed Internal error: e2ir.c 141 -
  • Fixed Internal error: ../ztc/elfobj.c 1251 -
  • Fixed Assertion failure: '!needThis()' on line 139 in file 'tocsym.c' -
  • Fixed Assertion failure: 'fdx->vresult' on line 1450 in file 'statement.c' -
  • Fixed Assertion failure: '!deferred.dim' on line 470 in file 'module.c' -
  • Fixed Assertion failure: 'sym->memtype' on line 3020 in file 'mtype.c' -
  • Fixed infamous std.string.toStringz() bug. -
- -
-

- What's New for - D 0.112 -

- -Jan 26, 2005 -

- -Note: This is a library only change, the dmd executables are still -at 0.111. - -

New/Changed Features

- - -
-

- What's New for - D 0.111 -

- -Jan 15, 2005 - -

New/Changed Features

-
    -
  • Added std.date.toUTCString(). -
  • \uFFFE and \uFFFF are now allowed as valid UCS characters, - since there are applications that use them. -
  • Added std.string.toString(long, uint) and toString(ulong, uint) - for radix conversions. -
  • Incorporated Phobos improvements provided by Ben Hinkle: -
    - I've attached modified versions of std.stream and mmfile and the help - section for std.mmfile and std.stream. - The std.mmfile changes are: -
      -
    • change module declaration to std.mmfile -
    • change class declaration to not be auto -
    • add mMode read-only property to get the file mode of type MmFile.Mode -
    - The std.stream changes are: -
      -
    • added Dave Fladebo's performance improvements for buffered readLine -
    • fixed a bug in read/write cfloat/cdouble/creal endian support -
    • uncommented MmFileStream and cleaned it up to use MmFile's mode property. -
    -
    -
- -

Bugs Fixed

-
    -
  • Fixed .length bug in std.string.sformat(). -
  • Fixed rounding error in std.date for dates before 1970. -
  • Fixed bugs with function inlining and length property. -
  • Compensated for errors in linux's powl() function. -
  • Fixed rounding problem with convering doubles to ulongs. -
  • Extended range of std.date daylight savings time calculation - under linux. -
- -
-

- What's New for - D 0.110 -

- -Dec 30, 2004 - -

New/Changed Features

-
    -
  • Structs can now be forward referenced. -
  • Structs can now be used as keys in associative arrays. -
  • Arrays of structs can now be sorted. -
  • Drastically speedup up compiler with projects that contain - complicated imports. -
  • Does a better job soldiering on after errors are diagnosed. -
  • .sizeof property can no longer be overridden. -
- -

Bugs Fixed

-
    -
  • Fixed regression on using super or this outside of a class. -
  • Fixed internal error cod1 2729. -
  • Object file now deleted if compilation errors occurred. -
  • Fixed some circumstances where properties were not recognized. -
  • Fixed potential hang in critical section release code. -
  • Fixed pointer value returned by 'in' expressions. -
  • Fixed codegen bug with some array initializations. -
  • Fixed access violation in std.uri.encodeComponent(). -
- -
-

- What's New for - D 0.109 -

- -Dec 5, 2004 - -

New/Changed Features

-
    -
  • super.id and this.id now work if id does not need a 'this' - pointer. -
- -

Bugs Fixed

-
    -
  • Fixed constant folding problem with complex numbers. -
  • Fixed class member initialize bug. -
  • Fixed compiler gpf on bit sizeof. -
  • Now correctly diagnoses some forward reference errors. -
  • Fixed error recovery on minusing template as a variable. -
  • Fixed internal error e2ir 1158 -
  • Fixed Assertion failure: '0' on line 661 in file 'expression.c' -
  • Fixed synchronized property call omitting (). -
- -
-

- What's New for - D 0.108 -

- -Nov 30, 2004 - -

Bugs Fixed

-
    -
  • Fixed mango build break. -
- -
-

- What's New for - D 0.107 -

- -Nov 29, 2004 - -

New/Changed Features

-
    -
  • Improved speed of writef(). -
  • Improved single thread performance of gc allocation - per Dave Fladebo's suggestions. -
  • InExpressions now, instead of returning a bit, - return a pointer to the associative array element if the key - is present, null if it is not. This obviates the need - for many double lookups. -
  • .offset property is now deprecated, use .offsetof - instead. This makes for better compatibility with C and fewer conflicts - with offset as a field name. -
  • Added .ptr property to arrays, which is handier and - more typesafe than casting an array to a pointer. -
  • Added Ben Hinkle's changes to std.stream: -
      -
    1. adds EndianStream for BOM and endian support. -
    2. removes the two public imports std.string and std.file from end of - file -
    3. adds read/write for ifloat, idouble, cfloat, cdouble and dchar to - interfaces InputStream and OutputStream and add implementations to - Stream and EndianStream -
    -
  • Added std.c.stddef for definition of C wchar_t. -
- -

Bugs Fixed

-
    -
  • Fixed internal error e2ir 814 -
  • Fixed protection of implicit constructor. -
  • Fixed deprecated attribute overriding static. -
  • Tightened up detection of constants being implicitly - converted to a type that cannot hold it. -
  • Now detects duplicate case strings in switch statements. -
  • Added support for switch(dchar[]) statements. -
  • Fixed bug reading source files without B.O.M. -
  • Fixed initialization of anonymous structs in classes. -
  • Anonymous structs/unions can now only be a member of an - aggregate. -
  • Assert expressions are no longer evaluated for side effects - even if asserts are turned off. It is not legal to depend on - the side effect of an assert. -
  • Fixed _init vs __init prefix for TypeInfo classes. -
  • Adjusted arithmetic conversion rules to match C99. -
- -
-

- What's New for - D 0.106 -

- -Nov 9, 2004 - -

New/Changed Features

-
    -
  • Changed std.c.time.CLOCKS_PER_SEC - from 1000 to 1000000 for linux. -
  • Added version identifier all being always set. -
  • Setting one of the list of - predefined version identifiers - is now an error. -
  • Changed TypeInfoClass to TypeInfo_Class. -
  • Changed TypeInfoTypedef to TypeInfo_Typedef. -
  • Incorporated Matthew Wilson's changes to std.process. -
- -

Bugs Fixed

-
    -
  • Fixed internal error s2ir 458 -
  • Fixed Assertion failure: 64 tocvdebug.c -
  • Fixed codegen error with EAX parameter. -
  • Version switch syntax checking fixed. -
  • Fixed cast of constant to bit. -
  • Multiple declarations of the same type alias now detected. -
  • Access check now done for private constructor in new expression. -
  • Anonymous structs/unions can now have non-field members. -
  • Non-top level classes now added to module class list. -
  • Fixed bugs in std.format with class objets, typedefs, - %o and %b formats. -
  • Fixed optimizer bug with loop invariants. -
  • Fixed synchronized statements on Linux. -
- -
-

- What's New for - D 0.105 -

- -Oct 28, 2004 - -

New/Changed Features

-
    -
  • Changed integral literal type determination to match C99 6.4.4.1. -
- -

Bugs Fixed

-
    -
  • Incorporated David Friedman's fixes for static initializers. -
  • Incorporated David Friedman's fixes for bit array duping - and array appending. -
  • Incorporated David Friedman's fix for cast of integral constant to bit. -
  • Incorporated Stewart Gordon's fix for switcherr.d and array.d. -
  • Fixed several bugs with dmd command line parsing. -
  • Fixed Assertion failure: 'ei' line 2576 file 'mtype.c' -
  • Fixed Ivan Senji's two compiler crashes. -
  • Fixed Internal error: ..\ztc\cod3.c 736 -
  • Fixed diagnostic on forward referenced templates. -
  • Fixed diagnostic on missing identifiers in foreach declarations. -
  • Fixed bug with mixin constructors. -
  • Internal use of "_invariant" changed to "__invariant" to avoid - conflicts with user code. -
  • Fixed dmd hang on transcoding some utf strings. -
  • Interfaces used as an argument to synchronized statements - are now automatically cast to Object. -
- -
-

- What's New for - D 0.104 -

- -Oct 21, 2004 - -

Bugs Fixed

-
    -
  • Fixed linker bug with unknown CV version. -
- -
-

What's New for D 0.103

- -Oct 20, 2004 - -

New/Changed Features

-
    -
  • Improved symbolic debug info generation for Win32. -
  • Added Dwarf2 line number debug info for linux. -
  • Added Dave Fladebo's speedups to associative arrays. -
- -

Bugs Fixed

-
    -
  • Removed redundant declaration of MAP_FAILED from Phobos. -
  • Fixed codegen scheduling bug. -
  • Incorporated Dave Fladebo's linux phobos makefile improvements. -
  • Incorporated David Friedman's std.thread pause fix. -
- -
-

What's New for D 0.102

- -Sep 20, 2004 - -

New/Changed Features

-
    -
  • Upgraded etc.c.zlib to 1.2.1 (thanks to Sean Kelly). -
  • Improved performance of array append (thanks to Dave Fladebo). -
  • Added \dmd\bin\make.exe. -
  • Improved Phobos makefiles. -
- -

Bugs Fixed

-
    -
  • Fixed private module construction order. -
  • Folded in Dave Fladebo's fix to std.zlib. -
  • Fixed array append seg fault under linux. -
  • Fixed problem where COMDATs could not exist in multiple modules. -
  • Fixed seg fault on const fields as lvalues. -
  • Fixed Internal error: ../ztc/cod1.c 2498 -
  • Fixed Internal error: e2ir.c 447 -
  • Fixed seg fault with empty debug statement. -
  • Fixed seg fault with undefined qualified types. -
  • Fixed error recovery with void in arithmetic expressions. -
  • Fixed assertion failure 1147 in expression.c. -
  • Fixed Internal error: ../ztc/cod2.c 4207 -
  • Eliminated trailing 0 in returned array from std.file.getcwd() -
  • Fixed "cd" command in make.exe. -
- -
-

What's New for D 0.101

- -Aug 30, 2004 - -

New/Changed Features

-
    -
  • Added Ben Hinkle's improvements to std.stream. Ben writes: - "I've attached a modified version of std.stream and phobos.html that - include the bug fixes and behavior changes outlined in the newsgroup - post yesterday. The bug fixes are almost entirely backwards compatible. - The biggest difference is the change that opening a file on Windows with - FileMode.In errors when the file doesn't exist. That makes it the same - behavior as Linux and it just seems to make sense. - I also did things like added writef and changed the Error classes to - Exception." - -
  • Kris pointed out that version identifiers have global effect, - and are dependent on which order modules are imported. This is clearly - wrong. Now, only version and debug definitions on the command line - have global effect. Others only influence the module they are - declared in. Furthermore, version and debug definitions can only - be done at module scope. -
- -

Bugs Fixed

-
    -
  • Fixed "super" bug introduced by 0.99. -
  • Missing function body after 'in' now diagnosed. -
  • Function literals can now have same type signature. -
  • Fixed problem with 'out' parameters in nested functions. -
  • Fixed array initialization causing seg fault. -
  • Fixed compiler gpf on invalid enum syntax. -
  • Fixed Internal error: ..\ztc\cod1.c 3251 -
  • Fixed FPU stack overflow bug. -
  • Fixed float optimization bug. -
  • Fixed bug in conversion of string literals to UTF-16. -
- -
-

What's New for D 0.100

- -Aug 20, 2004 - -

Bugs Fixed

-
    -
  • Fixed Internal error: ..\ztc\cgcs.c 213 introduced by 0.99. -
  • Hopefully fixed linux seg fault ENTER problem. -
- -
-

What's New for D 0.99

- -Aug 19, 2004 - -

New/Changed Features

-
    -
  • Added std.string functions ifind() and irfind() (thanks - to David L. Davis). -
  • Slicing of bit arrays now allowed if lower bound lands - on a byte boundary. -
  • Bit pointer offsets now are in number of bits, however, - they must be a multiple of 8. -
  • Improved performance of stack array initialization. -
  • Idiom of using std.c.stdlib.alloca() with a constant value - now recognized. -
  • Removed implicit cast to void. What was I thinking? -
  • Moved setErrno() from std.c.linux.linux to std.c.stdlib. -
  • Added setErrno() to std.c.stdlib. -
  • Improved code gen on cast of 'this' to interface. -
  • Added implicit declaration of length to index and slice - expressions. This will break existing code if length is used - as a variable within [ ]. -
- -

Bugs Fixed

-
    -
  • Some overloading errors fixed. -
  • ~ now works on bit operands. -
  • Copy of non-byte aligned upper bound of bit array copies - no longer copies too many bits. -
  • Fixed cast of bit to byte. -
  • Fixed MI bug with interface vtbl dispatch. -
  • Fixed Internal error: ..\ztc\el.c 723 -
  • Fixed gpf on forward reference of mixin. -
  • Fixed Internal error: ..\ztc\dt.c 104 -
  • Fixed Internal error: ..\ztc\cgcod.c 552 -
  • Fixed error recovery on bad initializers. -
  • Diagnoses error on arithmetic on class references. -
  • Fixed Internal error: ..\ztc\cgcod.c 1464 -
  • Fixed internal error: ..\ztc\cgcs.c 353 -
  • Fixed unresolved external when expanding nested templates in - imports. -
  • Fixed mysterious TOK881 message. -
  • Fixed compiler gpf with using const char[] as enum value. -
  • Fixed compiler gpf with error recovery. -
- -
-

What's New for D 0.98

- -Aug 5, 2004 - -

New/Changed Features

-
    -
  • One can now 'new' a scalar type, for example:
    - int* p = new int; -
- -

Bugs Fixed

-
    -
  • Fixed bug where typedef/alias members of a class weren't found - when looked up via an instance of that class. -
  • Added Berin Loritsch's fixes to pi.d. -
  • Better detection of recursive template instantiation errors. -
  • Improved error message for implicit conversion errors. -
  • Fixed gpf on erroneous template instantiations. -
  • Fixed name mangling of D __import__ symbols from DLLs. -
  • Fixed Assertion failure: 267 'declaration.c' -
  • Fixed Internal error: ..\ztc\cgcod.c 1464 -
  • Fixed Assertion failure: 1204 'expression.c' -
  • Fixed some error recovery for undefined identifiers. -
  • Fixed Internal error: ..\ztc\cgcs.c 350 -
  • Fixed Internal error: ..\ztc\cod1.c 2244 -
  • Access checking now done after overload resolution rather - than before. -
  • Fixed gpf on static initializers for function local structs. -
  • Fixed error recovery on undefined identifiers. -
  • Fixed gpf on const arrays without initializers. -
  • Fixed Assertion failure: 3154 'mtype.c' -
  • Fixed Assertion failure: 1203 'func.c' -
  • Fixed Internal error: ..\ztc\cg87.c 1968 -
- -
-

What's New for D 0.97

- -Jul 26, 2004 - -

New/Changed Features

-
    -
  • Added missing overload (opPos) for unary plus. -
  • B.O.M. no longer required for UTF-16 and UTF-32 source - text (thanks to Arcane Jill). -
- -

Bugs Fixed

-
    -
  • Fixed linux bug where sometimes global symbols were not - made public in .o file. -
  • Fixed linux bug with function returns of small structs - from C functions. -
  • Implemented listdir() for linux (thanks to Christopher E. - Miller and Andre Fornacon) -
  • Deprecated functions can now call other deprecated functions - without causing an error. -
  • Check for deprecated functions now done after overloading - rather than before. -
  • Fixed some forward reference problems with interfaces. -
  • Fixed compiler GPF with va_arg. -
  • Fixes for std.system (thanks to Thomas Kuehne) -
  • Fixed method alias ordering conflict in derived class. -
  • Fixed std.utf bugs (thanks to Stewart Gordon) -
- -
-

What's New for D 0.96

- -Jul 21, 2004 - -

New/Changed Features

-
    -
  • Added exec* functions to std.process. (thanks to Matthew Wilson) -
  • Added std.perf (thanks to Matthew Wilson) -
- -

Bugs Fixed

-
    -
  • Fixed compiler crash on circular class derivations. -
  • Invalid UTF characters in string literals now diagnosed. -
  • Date parsing can now handle time zone offsets that are not - in hourly increments. -
  • Fixed incorrect handling of precision for strings in std.format. -
  • Fixed auto bug inside template bodies. -
  • Fixed static initializations of the form int[2]x=3; -
  • Added some missing line numbers in error messages. -
  • Fixed an alias resolution problem. -
  • Break/continue in try and syncrhonized blocks now matches - documentation. -
  • Function out parameters are now initialized at the start - of the function. -
  • Fixed mishandling of out parameters in variadic functions. -
  • Fixed problem of undefined symbols at link time when templates are - expanded in interface declarations. -
  • Template default arguments for parameters now are 'lazilly' - semantically analyzed, which means they can refer to previous template - argument types. -
  • Fixed DMD GPF when trying to index a mixin with []. -
  • time_t definition removed from std.c.linux.linux, as it conflicted - with definition in std.c.time. -
- -
-

What's New for D 0.95

- -Jul 6, 2004 - -

New/Changed Features

-
    -
  • Added printf replacement, std.stdio.writef and related - functions. -
  • Added std.format for formatting strings. -
  • Rewrote std.string.format() for full functionality. -
- -

Bugs Fixed

-
    -
  • Fixed Internal error: ..\ztc\cgcod.c 614 -
  • Fixed overflow detection on static array dimension. -
  • Fixed Internal error: ..\ztc\cod4.c 352 -
  • Now detects attempts to use non-identifer character filenames - as module names. -
  • Can now overload static member functions with non-static ones - within a static one. -
  • Now detects attempts to overload destructors. -
  • Fixed compiler exit status under linux (thanks to Sam McCall). -
  • Fixed poor error recover from undefined template identifier. -
  • Better forward reference handling. -
  • Fixed problems with local statics having name collisions. -
- -
-

What's New for D 0.94

- -Jun 27, 2004 - -

Bugs Fixed

-
    -
  • Missing TypeInfo for bit added. -
  • Incorrect integral type promotion for variadic arguments fixed. -
  • Fixed std.string.toStringz() 0 termination bug. -
  • Fixed some .size => .sizeof deprecations in library. -
  • Fixed std.stream.File.open() and std.stream.File.create() - to handle UTF filenames (thanks to Carlos Santander Bernal). -
  • Fixed std.uri.encode() bug with Octets. -
  • Fixed codegen error with typedef'd static arrays. -
  • Correct error message now generated when using an array - initializer as an expression. -
  • Fixed "frame" error when compiling. -
  • Fixed compiler GPF on getting boolean value of module name. -
  • Fixed compiler GPF with function with all default arguments. -
  • Fixed bug with associative array typedef'd indices. -
  • Fixed TypeInfo crash with arrays of null Objects. -
  • Fixed Internal error: ..\ztc\blockopt.c 1941 -
  • Fixed Internal error: ..\ztc\cod1.c 2244 -
  • Fixed Assertion failure: '0' on line 80 in file 'mtype.c' -
- -
-

What's New for D 0.93

- -Jun 22, 2004 - -

New/Changed Features

-
    -
  • char.init is now 0xFF, wchar.init is 0xFFFF, dchar.init - is 0x0000FFFF. Thanks to Arcane Jill. -
  • Array operator assignment overloading with opIndex(index, value) is now - deprecated. Use opIndexAssign(value, index) instead. -
  • Multiple indices are now allowed with array operator - overloading. -
  • Added _arguments[] and _argptr to - variadic functions. -
  • Added - TypeidExpressions. -
  • .typeinfo property is now deprecated (use - TypeidExpression instead). -
  • Replaced std.c.stdarg with std.stdarg. -
- -

Bugs Fixed

-
    -
  • Some minor error message improvements. -
  • Fixed bug where local class static constructor did not get - called. -
  • Fixed Assertion failure: 'f' on line 2695 in file 'expression.c' -
  • Fixed Internal error: ..\ztc\cgcs.c 353 -
  • Fixed dmd GPF when module used as array. -
- -
-

What's New for D 0.92

- -Jun 7, 2004 - -

New/Changed Features

-
    -
  • Modified Object.toString() and Object.print() to print - out the name of the object instance's class. -
  • The Expression within an array's brackets is - now an AssignExpression (meaning that commas are no - longer allowed). -
  • Added default arguments to function parameters. Semantics - are like C++. -
  • Added package attribute for package level access. -
  • Added operator overloads opAdd_r, opMul_r, opAnd_r, - opOr_r, and opXor_r. -
  • Modified operator overloading rules - so functionality can be added to the lvalue of an operator overload - for user defined rvalues - without needing to modify the lvalue's class. -
- -

Bugs Fixed

-
    -
  • Fixed parsing bug in typeof(this).func(); -
  • Fixed nested multiple inheritance bug with interfaces. -
  • Fixed compare() bug in typeinfo's for int and uint. - Thanks to Stewart Gordon. -
- -
-

What's New for D 0.91

- -May 27, 2004 - -

New/Changed Features

-
    -
  • Allow functions that return void to return expressions. -
  • Added support for typeof(this) - and typeof(super). - outside of non-static member functions. -
  • Added cast operator overloading. -
  • typeof(this).member() now does non-virtual call to member(). -
  • Mixin qualifier names now work for class members. -
- -

Bugs Fixed

-
    -
  • Fixed std.file.listdir unicode issue with Win95. -
  • Fixed incorrect diamond inheritance of interface classes. -
  • std.string.capwords() now converts non-first characters - of a word to lower case. -
  • Fixed problem with super in mixins. -
  • Fixed assert failure mtype.c 2575 -
  • Fixed bad formatting of typedef* error messages. -
  • Fixed std.string.toString(char). -
  • Fixed bug accessing private static from inlined function. -
  • Fixed compiler gpf on synchronized blank for statement inits. -
- -
-

What's New for D 0.90

- -May 20, 2004 - -

Bugs Fixed

-
    -
  • Fixed problem with mixins overriding same function more than once. -
  • Added ability for invariants and other special functions - to be in mixins. -
  • Fixed error diagnostic for delegate literals in class declarations. -
  • Fixed extended comparison operators so they work on integral - types when constant folding. -
  • Fixed bug with mixin functions for interfaces. -
  • Fixed Internal error: ..\ztc\cod1.c 1641 -
  • Fixed name lookups for special functions in mixins. -
- -
-

What's New for D 0.89

- -May 17, 2004 - -

New/Changed Features

-
    -
  • Allow void() to be omitted from function literals. -
  • Mixins added. -
  • A WithStatement now works on struct instances. -
- -

Bugs Fixed

-
    -
  • Added Stewart Gordon's windows.d function pointer fixes. -
  • Added Stewart Gordon's std.asserterror fixes. -
  • Added Ben Hinkle's std.stream fixes. -
  • Fixed bug with template function alias arguments. -
- -
-

What's New for D 0.88

- -May 5, 2004 - -

New/Changed Features

-
    -
  • Added std.c.stdarg (thanks to Hauke Duden). -
  • C style casts deprecated (use -d to compile them for now). -
  • instance style template instantiation deprecated - (use -d to compile them for now). -
- -

Bugs Fixed

-
    -
  • Fixed problem with template classes and opCall. -
  • Fixed problems with implicit this and member template functions. -
  • Fixed problem with property in [] of NewExp. -
  • Now correctly diagnoses problem with using local as template - parameter alias. -
  • Fixed bug with no identifier for declarator in template type. -
  • Fixed const folding with ?: operator. -
  • Fixed std.utf.toUTF32() with J C Calvarese's fix. -
  • Included David Friedman's fixes for linux monitors. -
  • Fixed bug with overloading alias template parameters. -
  • Fixed internal error cg87 1235. -
  • Superclass dtors now called for class deallocator. -
  • Fixed _d_delmemory() taking the wrong argument. -
  • Fixed auto super dtors. -
  • Fixed multi argument struct new's with custom new. -
  • Fixed custom deallocator struct delete. -
  • Monitors now deleted when object is deleted. -
- -
-

What's New for D 0.86

- -Apr 23, 2004 - -

New/Changed Features

-
    -
  • Added template default parameters. -
  • Added casting ability to non-COM interfaces. -
  • Added Christopher E. Miller's std.socket and std.socketstream. -
  • Added std.mmfile (thanks to Matthew Wilson!) -
- -

Bugs Fixed

-
    -
  • An error is now issued when the argument to delete - is a COM interface object. -
  • Incorporated Antonio Monteiro's fixes for std.date and std.zip. -
  • Error now diagnosed when EnumBaseType is not integral. -
  • Fixed delete on non-class objects. -
- -
-

What's New for D 0.82

- -Mar 28, 2004 - -

Bugs Fixed

-
    -
  • Some cases of forward referenced classes are now handled. -
  • Illegal recursive alias declarations now correctly diagnosed. -
  • Erroneous anonymous struct member offsets within unions fixed. -
  • Fixed problem with array initializers for consts. -
  • Fixed bug with intrinsics. -
  • Can now slice a void[]. -
  • std.date: fixed dst calculation for zones with no dst. -
  • Fixed bug with nested delegate literals. -
  • Fixed overload inheritance bug with function aliases from - base classes. -
  • Added files gnuc.h, mem.h, mem.c, port.h, enum.h, and enum.c - to the \dmd\src\dmd. -
  • Fixed seg fault on forward reference to template. -
  • Fixed std.date.getUTCtime() for linux. -
- -
-

What's New for D 0.81

- -Mar 7, 2004 - -

Bugs Fixed

-
    -
  • Fixed problem with class and modules having the same name. -
  • Fixed access problem with protected members of base class. -
- -
-

What's New for D 0.80

- -Mar 5, 2004 - -

New/Changed Features

-
    -
  • Added overloads for basic types for std.string.toString(). -
  • Modified front end source to be more compatible with GDMD project. -
  • Implicit conversions of floating point values to integer - values is now disallowed. -
- -

Bugs Fixed

-
    -
  • Fixed dmd crash with module and class name conflict. -
  • Fixed bug where f(x)(y); was interpreted as declaring - x as a function taking parameter type y and returning type f, - instead of f being an instance of a class with () overloaded. - There's still the problem of f(*p)(y), though, the solution - is to probably just deprecate the C function pointer declaration - syntax. -
  • Fixed using super in nested function. -
  • Function members without bodies in non-abstract classes - now reference an external - symbol rather than inserting a 0 in the vtbl[]. -
  • Fixed Internal error: ../ztc/cgcod.c 1459 -
  • Fixed problems with template aliases. -
  • Improved semantic analysis with member templates. -
  • Adding some missing file/line numbers to error messages. -
  • Fixed bug with property syntax in return expression. -
  • Fixed problem with template expansion contexts. -
- -
-

What's New for D 0.79

- -Feb 2, 2004 - -

New/Changed Features

-
    -
  • Added utf decoding capability to foreach statement. -
  • Added Christopher Miller's std.base64. -
  • Fixed gc per http://www.digitalmars.com/drn-bin/wwwnews?D/21217 -
- -

Bugs Fixed

-
    -
  • Fixed std.file failure on Win95 (hopefully got it right this time!). -
  • Fixed code gen error with unsigned % 10. -
  • Fixed problem with std.regexp.test and multiple calls. -
  • Fixed Internal error: ..\ztc\cgcod.c 2241 -
  • Fixed chained assignments to bit arrays. -
  • Fixed bugs with foreach over a bit array. -
  • Fixed many problems with recursive templates. -
  • Fixed Assertion failure on line 67 in file 'template.c' -
  • Fixed problem with optimization of short registers. -
- -
-

What's New for D 0.78

- -Jan 14, 2004 - -

New/Changed Features

-
    -
  • std.string.find() and .rfind() upgraded to support dchar - searches within char[] strings. -
  • Fixed std.ctype functions to accept/return dchar types - instead of char types. -
  • // comments can now be terminated by end of file rather - than a newline. -
- -

Bugs Fixed

-
    -
  • Fixed Internal error e2ir.c 133 -
  • Fixed Internal error: ..\ztc\cod1.c 2240 -
  • Fixed Internal error: ..\ztc\cod2.c 4116 -
  • Fixed crash on invalid template syntax. -
  • std.file functions now fall back to "A" functions - on Win9x systems. -
  • Fixed problem with static arrays of structs with non-zero - default initializations. -
  • Fixed crasher with structs declared but not defined. -
  • Fixed critical section bug in Win95. -
- -
-

What's New for D 0.77

- -Jan 2, 2004 - -

New/Changed Features

-
    -
  • Changed std.file so unicode filenames work. -
  • Added toUTF16z to std.utf. -
  • Added std.md5. -
  • Hex strings must now contain an even number of hex digits. -
  • Added .alignof property. -
  • Added .sizeof property which has same value as - .size, but won't conflict with C/C++ struct member names. -
  • Global main must be main() or main(char[][] args). -
  • Added size_t, ptrdiff_t predefined aliases. - Use size_t as an alias for an unsigned integral type spanning - the address space, and ptrdiff_t as an alias for a signed - integral type spanning the address space. This will make the code - portable from 32 to 64 bits. -
  • .length, .size, .sizeof, and .alignof - now return a value of type size_t. -
  • For win32, converts '/' in source file names passed to dmd - to '\' so that - back end routines work consistently. -
  • Added typeof. -
  • Added pragmas. -
  • Added expression lists to - case statements. -
  • Added goto default; and goto case; and - goto case Expression; - for use in switch statements. -
  • Added template alias - parameters. -
  • Added new template instance syntax. -
  • Added class template syntax. -
  • Added template member injection rule. -
  • Added Matthew Wilson's std.recls - for recursive file-system searching. -
- -

Bugs Fixed

-
    -
  • Better error recovery in parser. -
  • Sizes of bit arrays fixed. -
  • Fixed conflict between std.intrinsic and std.math. -
  • Fixed reset problem with std.regexp.match(). -
  • Fixed std.string.rfind(). -
  • Fixed several problems with -inline. -
- -
-

What's New for D 0.76

- -Nov 21, 2003 - -

New/Changed Features

-
    -
  • std.assert changed to std.asserterror. -
  • Added keyword is, which has same function as ===. -
  • Renamed operator overloading names. -
  • Renamed std.assert to std.asserterror. -
  • Added system to std.process. -
  • Changes to std.file: -
      -
    • Added several functions to std.file. -
    • Changed byte[] types for data in std.file to void[]. -
    • std.file.getSize() now returns a ulong. -
    -
- -

Bugs Fixed

-
    -
  • Library modules are all correctly named. -
  • Library modules now have private imports. -
- -
-

What's New for D 0.75

- -Nov 4, 2003 - -

New/Changed Features

-
    -
  • Changed to new standard library package layout. -
  • Changed apply to opApply. -
  • Fixed foreach so it - can have multiple parameters. -
  • Added etc.c.zlib, a D interface to the C zlib compression library. -
  • Added std.zlib, a compression module. -
  • Added std.zip, a zip archive module. -
- -
-

What's New for D 0.74

- -Oct 15, 2003 - -

New/Changed Features

-
    -
  • Added support for Unicode characters in identifiers. -
  • Version declarations can now wrap attribute : and they'll stick. -
  • -offilename switch now accepts any extension. -
  • Added D.win32.registry. -
- -

Bugs Fixed

-
    -
  • Problems fixed with with abstract member function definitions. -
  • Fixed problems with getting the wrong .classinfo with inherited classes. -
  • Fixed internal error cgcod.c 1459 -
  • Fixed internal error e2ir.c 721 -
  • Fixed ICE for empty foreach bodies. -
  • Fixed name mangling for out/inout parameters to extern (Windows) functions. -
  • Fixed bug in ?: of string literals. -
  • Fixed order-of-evaluation bug with &((new foo()).bar) -
  • Can now assign null to delegates. -
  • Fixed problem diagnosing error of slices as out parameters. -
  • Fixed problem diagnosing error of const field initializations. -
  • Fixed gc and multithread deadlock (thanks to jhenzie). -
- -
-

What's New for D 0.73

- -Sep 18, 2003 - -

New/Changed Features

-
    -
  • Added static asserts. -
  • Added bswap as a compiler intrinsic function. -
  • Added operator overloading - for array index [], - array slice [..] and - function call () operators. -
  • Added properties. -
  • To take the address of a function, the & operator is - required now, rather than being implicit. -
- -

Bugs Fixed

-
    -
  • Implicit conversions of B[] to A[] are no longer allowed if B - is derived from A. Gaping type safety holes are the reason. -
- -
-

What's New for D 0.72

- -Sep 14, 2003 - -

New/Changed Features

-
    -
  • Implicit conversions of B[] to A[] are now allowed if B - is derived from A. -
  • Functions in abstract classes can now have function bodies. -
- -

Bugs Fixed

-
    -
  • Fixed bug with in and out instructions in inline assembler. -
  • Fixed speed problem with %.*s printf format. -
  • Fixed problem with foreach over array of arrays or structs. -
  • Fixed compiler error with array rehash. -
  • Now correctly issues error on self-initializations like:
    - int a = a;
    -
  • Fixed problem converting "string" to char[], it should be - an exact conversion, not an implicit conversion. -
- -

Linux Bugs Fixed

-
    -
  • Occaisional segfault during gc collection fixed. -
  • Empty static arrays now placed in BSS segment. -
  • Conversion of uint to real now works. -
- -
-

What's New for D 0.71

- -Sep 3, 2003 - -

New/Changed Features

- - -

Bugs Fixed

-
    -
  • Fixed bug with nested functions. -
  • Fixed bug with linux file.write() and file.append() functions. -
  • Fixed bug with linux processing of /etc/dmd.conf. -
- -
-

What's New for D 0.70

- -Aug 24, 2003 - -

New/Changed Features

-
    -
  • Added wprintf() to object.d. -
  • Extended alias - to work for overloaded functions from another scope. -
- -

Bugs Fixed

-
    -
  • Fixed incorrect handling of leading UTF-8 BOM mark. -
  • Fixed 2 compiler GPF's. -
  • Fixed problem with downcasting to interfaces. -
  • Fixed linux seg fault with %@P% in DFLAGS. -
  • Fixed inoperative -L switch for linux. -
- -
-

What's New for D 0.69

- -Aug 11, 2003 - -

New/Changed Features

-
    -
  • Added dchar keyword for UTF-32 characters. -
  • ' ' strings are now character literals, not strings. -
  • wysiwyg strings are not r"string", not 'string'. -
  • `string` (backquotes) are also wysiwyg strings. -
  • Added x"0a AA BF" style hex strings. -
  • Implicit conversion of single character strings to - character literals no longer happens. -
  • Implicit conversions of string literals between UTF-8, - UTF-16 and UTF-32 now happens. -
  • Deleted command line switch -o, replaced it with - -od, -of and -op. This should remove - confusion and add flexibility. -
  • Added bool as an alias for bit. -
  • Integer and floating point literals can now have embedded - _ for formatting purposes. -
- -

Bugs Fixed

-
    -
  • Bit variables can now be out or inout function - parameters. -
  • Package names now part of mangled names. -
  • Mangled names are now reversible unambiguously. -
  • Fixed problem returning 8 byte structs from functions. -
  • Fixed bug with typedef'd associative arrays. -
  • Fixed bug with typedef'd return values. -
  • Fixed error recovery from 'typedef struct'. -
  • Fixed problems with Linux exception handling. -
  • 0b... numeric literals now work under Linux. -
- -
-

What's New for D 0.68

- -Jul 8, 2003 - -
    -
  • Added TypeInfo's for classes and other basic types. -
  • new'ing arrays of types with non-zero initializers now works. -
  • new'ing bit arrays now works. -
  • new'ing structs now works. -
  • Fixed bug with typedef'd associative array index. -
  • Falling off the end of a function that has a non-void return - type now generates a runtime exception if a syntax error is not - already generated. -
  • Fixed parse bug with inout keyword in nested functions. -
  • Fixed cgcs 350 error. -
  • Fixed error where const objects could be assigned to. -
  • Fixed crash with non-existent struct member names in initializers. -
  • Fixed crash with const objects with no initializers. -
  • Fixed cgobj 3115 error. -
  • Correctly errors out now when slicing voids. -
- -
-

What's New for D 0.67

- -Jun 17, 2003 - -
    -
  • Fixed some bugs. -
- -
-

What's New for D 0.66

- -Jun 8, 2003 - -
    -
  • Added uri module. -
  • Added utf module. -
  • Added constant folding for ?: operator. -
  • Zero initialized structs no longer need to link to - the module the struct was defined in. -
  • Private imports now supported. -
  • Class names common to multiple modules no longer collide, - but this required a change to how class names are mangled. - Hence, existing libraries will need to be recompiled. -
  • templates of the form: -
    -	template foo(T:T[])
    -	
    - now correctly resolve T in foo(int[]) to int rather than int[]. -
- -
-

What's New for D 0.65

- -May 13, 2003 - -

linux version

- -
    -
  • Another bad section name bug is hopefully fixed. -
- -
-

What's New for D 0.64

- -May 12, 2003 - -

linux version

- -
    -
  • dmd.conf now needs to be installed as - /etc/dmd.conf. -
  • phobos.a has been renamed as libphobos.a - and been placed in the /usr/lib directory. -
  • dmd will now do the link step automatically. -
  • The bad section name bug is hopefully fixed. -
- -
-

What's New for D 0.63

- -May 10, 2003 - -
    -
  • Added linux version. Thanks to Burton Radons and - Pat Nelson for the help. -
- -
-

What's New for D 0.61

- -Mar 30, 2003 - -
    -
  • Incorporated Burton Radon's stream.d fixes. -
  • Improved performance of string switches and string concatenation. -
  • Phobos library is now built optimized. -
  • Fixed numerous reported bugs. -
- -
-

What's New for D 0.59

- -Mar 6, 2003 - -
    -
  • Fixed bugs in nested functions. -
  • Refactored code so it compiles with gnuc. -
- -
-

What's New for D 0.58

- -Mar 3, 2003 - -
    -
  • Added covariant function return types. -
  • Fixed several bugs in nested functions, - template argument deduction, access protections, - constant folding, etc. -
- -
-

What's New for D 0.57

- -Feb 25, 2003 - - - -Many thanks to Burton Radons for his help with this. - -
-

What's New for D 0.56

- -Feb 20, 2003 - -
    -
  • Fixed a couple bad bugs with template typedefs and arrays. -
- -
-

What's New for D 0.55

- -Feb 17, 2003 - -
    -
  • Added several new math functions to math.d. -
  • Changed behavior of new expressions to match change in - array declaration order: -
    -	char[][] foo;
    -	foo = new char[][45];	// new, correct way to allocate array of 45 strings
    -	//foo = new char[45][];	// old, now wrong, way
    -	
    -
  • Fixed some problems with error recovery. -
  • The module name is now in its own scope enclosing the scope - of the contents of the module (before it was simply inaccessible). -
- -
-

What's New for D 0.54

- -Feb 14, 2003 - -
    -
  • Fixed some parsing problems with template instances. -
  • Introduced new types cfloat, cdouble, ifloat, idouble. -
  • Introduced new constant types ifloat, idouble. -
  • Renamed extended to real. -
  • Renamed imaginary to ireal. -
  • Renamed complex to creal. -
  • Reversed order of array declarations when they appear - to the left of the identifier being declared. - Postfix array declaration syntax remains the same (and equivalent - to C). -
    -	int[3][4] a;	// a is 4 arrays of 3 arrays of ints
    -	int b[4][3];	// b is 4 arrays of 3 arrays of ints
    -
    -
- - These changes have been needed for a while, and it's time to - put them in before D gets too constrained by legacy code. - Fortunately, using grep and global/search/replace can easily - take care of the type renames. - The array declaration issue can be fixed - by grepping for "][", and then manually fixing each. - - -
-

What's New for D 0.53

- -Feb 8, 2003 - - - - -
-

What's New for D 0.52

- -Feb 5, 2003 - -
    -
  • The argument to a with statement can now be a template instance. -
  • The inline asm for FCOMI/FCOMIP/FUCOMI/FUCOMIP can now - accept the ST,ST(i) form of the instruction to match the - Intel documentation. -
  • Fixed numerous minor bugs. -
- - -
-

What's New for D 0.51

- -Jan 27, 2003 - -
    -
  • Added template value parameters (as opposed to just type parameters). -
  • Fixed several problems with templates. -
  • Added #line pragma support. -
  • D can now accept source files in various UTF formats. -
- - -
-

What's New for D 0.50

- -Nov 20, 2002 - -
    -
  • To convert to type bit now requires an explicit cast, - rather than implicit. The conversion (cast(bit)i) is - now performed as (i?true:false). - -
  • Added library functions string.toString(). - -
  • Fixed many template bugs. - -
  • Changed implicit conversion rules for integral types; - implicit conversions are not allowed if the value would change. - For example: -
    -	byte  b = 0x10;		// ok
    -	ubyte c = 0x100;	// error
    -	byte  d = 0x80;		// error
    -	ubyte e = 0x80;		// ok
    -	
    -
- - -
-

What's New for D 0.49

- -Nov 18, 2002 - -
    -
  • Added LINKCMD to sc.ini to specify which linker to use. -
  • Multiple -I switches can now be used, and the - paths are searched in order. -
  • Fixed bug in regexp with blank substitutions. -
  • Removed "reference to this before super()" error. -
  • % and %= floating point operations are now handled - by code generator instead of library. -
  • Fixed GCStats linking problem. -
  • Fixed many other minor problems. -
- - -
-

What's New for D 0.48

- -Oct 25, 2002 - -
    -
  • Added - conv to phobos library. -
  • Fixed a number of bugs that were blocking people. -
- - -
-

What's New for D 0.46

- -Oct 22, 2002 - -
    -
  • Fixed problem with auto class constructors. -
  • Fixed problem with calling class invariants with -O. -
  • Redid - lib.exe command syntax to simplify makefiles. -
  • String literals can now span multiple lines. -
  • Fixed bugs in handling access violations and other windows - exceptions. -
  • Revamped support for generating Windows GUI apps. -
  • Fixed some code gen bugs. -
- - -
-

What's New for D 0.45

- -Oct 8, 2002 - -
    -
  • Redid constructor semantics - to improve reliability. -
  • Expanded inlining capability. -
  • Redid interface semantics. -
  • Fixed problems with ~ string concatenation. -
- - -
-

What's New for D 0.44

- -Oct 1, 2002 - -
    -
  • Clarified interface semantics - and fixed problems with it per Joe Battelle's suggestions. -
- - -
-

What's New for D 0.43

- -Sep 28, 2002 - - - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Change Log + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Mon Oct 17 00:39:30 2005 +
+
+ + + + +$(D_S + + +

D Change Log

+ + + + +
+ +

+ What's New for + D 0.136 +

+ + +Oct 5, 2005 +

+ +

New/Changed Features

+ + +

Ddoc

+ + +

Bugs Fixed

+ + +
+ +

+ What's New for + D 0.135 +

+ + +Oct 2, 2005 +

+ +

New/Changed Features

+ + +

Ddoc

+ + +

Bugs Fixed

+ + +
+ +

+ What's New for + D 0.134 +

+ + +Sep 28, 2005 +

+ +

New/Changed Features

+ + +

Ddoc

+ + +

Bugs Fixed

+ + +
+ +

+ What's New for + D 0.133 +

+ + +Sep 24, 2005 +

+ +

New/Changed Features

+ + +

Ddoc

+ + +

Bugs Fixed

+ + +
+ +

+ What's New for + D 0.132 +

+ + +Sep 19, 2005 +

+ +

New/Changed Features

+ + + +
+ +

+ What's New for + D 0.131 +

+ + +Sep 8, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+ +

+ What's New for + D 0.130 +

+ + +Sep 6, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.129 +

+ +Aug 5, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.128 +

+ +Jul 10, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.127 +

+ +Jun 16, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.126 +

+ +Jun 7, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.125 +

+ +May 20, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.124 +

+ +May 19, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.123 +

+ +May 11, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.122 +

+ +May 3, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.121 +

+ +Apr 15, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.120 +

+ +Apr 6, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.119 +

+ +Mar 18, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.118 +

+ +Mar 12, 2005 +

+ +

Bugs Fixed

+ + +
+

+ What's New for + D 0.117 +

+ +Mar 10, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+ +

+ What's New for + D 0.116 +

+ + +Mar 7, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.115 +

+ +Feb 28, 2005 +

+ +

Bugs Fixed

+ + +
+

+ What's New for + D 0.114 +

+ +Feb 27, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.113 +

+ +Feb 12, 2005 +

+ +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.112 +

+ +Jan 26, 2005 +

+ +Note: This is a library only change, the dmd executables are still +at 0.111. + +

New/Changed Features

+ + +
+

+ What's New for + D 0.111 +

+ +Jan 15, 2005 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.110 +

+ +Dec 30, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.109 +

+ +Dec 5, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.108 +

+ +Nov 30, 2004 + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.107 +

+ +Nov 29, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.106 +

+ +Nov 9, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.105 +

+ +Oct 28, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

+ What's New for + D 0.104 +

+ +Oct 21, 2004 + +

Bugs Fixed

+ + +
+

What's New for D 0.103

+ +Oct 20, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.102

+ +Sep 20, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.101

+ +Aug 30, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.100

+ +Aug 20, 2004 + +

Bugs Fixed

+ + +
+

What's New for D 0.99

+ +Aug 19, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.98

+ +Aug 5, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.97

+ +Jul 26, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.96

+ +Jul 21, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.95

+ +Jul 6, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.94

+ +Jun 27, 2004 + +

Bugs Fixed

+ + +
+

What's New for D 0.93

+ +Jun 22, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.92

+ +Jun 7, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.91

+ +May 27, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.90

+ +May 20, 2004 + +

Bugs Fixed

+ + +
+

What's New for D 0.89

+ +May 17, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.88

+ +May 5, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.86

+ +Apr 23, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.82

+ +Mar 28, 2004 + +

Bugs Fixed

+ + +
+

What's New for D 0.81

+ +Mar 7, 2004 + +

Bugs Fixed

+ + +
+

What's New for D 0.80

+ +Mar 5, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.79

+ +Feb 2, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.78

+ +Jan 14, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.77

+ +Jan 2, 2004 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.76

+ +Nov 21, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.75

+ +Nov 4, 2003 + +

New/Changed Features

+ + +
+

What's New for D 0.74

+ +Oct 15, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.73

+ +Sep 18, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.72

+ +Sep 14, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +

Linux Bugs Fixed

+ + +
+

What's New for D 0.71

+ +Sep 3, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.70

+ +Aug 24, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.69

+ +Aug 11, 2003 + +

New/Changed Features

+ + +

Bugs Fixed

+ + +
+

What's New for D 0.68

+ +Jul 8, 2003 + + + +
+

What's New for D 0.67

+ +Jun 17, 2003 + + + +
+

What's New for D 0.66

+ +Jun 8, 2003 + + + +
+

What's New for D 0.65

+ +May 13, 2003 + +

linux version

+ + + +
+

What's New for D 0.64

+ +May 12, 2003 + +

linux version

+ + + +
+

What's New for D 0.63

+ +May 10, 2003 + + + +
+

What's New for D 0.61

+ +Mar 30, 2003 + + + +
+

What's New for D 0.59

+ +Mar 6, 2003 + + + +
+

What's New for D 0.58

+ +Mar 3, 2003 + + + +
+

What's New for D 0.57

+ +Feb 25, 2003 + + + +Many thanks to Burton Radons for his help with this. + +
+

What's New for D 0.56

+ +Feb 20, 2003 + + + +
+

What's New for D 0.55

+ +Feb 17, 2003 + + + +
+

What's New for D 0.54

+ +Feb 14, 2003 + + + + These changes have been needed for a while, and it's time to + put them in before D gets too constrained by legacy code. + Fortunately, using grep and global/search/replace can easily + take care of the type renames. + The array declaration issue can be fixed + by grepping for "][", and then manually fixing each. + + +
+

What's New for D 0.53

+ +Feb 8, 2003 + + + + +
+

What's New for D 0.52

+ +Feb 5, 2003 + + + + +
+

What's New for D 0.51

+ +Jan 27, 2003 + + + + +
+

What's New for D 0.50

+ +Nov 20, 2002 + + + + +
+

What's New for D 0.49

+ +Nov 18, 2002 + + + + +
+

What's New for D 0.48

+ +Oct 25, 2002 + + + + +
+

What's New for D 0.46

+ +Oct 22, 2002 + + + + +
+

What's New for D 0.45

+ +Oct 8, 2002 + + + + +
+

What's New for D 0.44

+ +Oct 1, 2002 + + + + +
+

What's New for D 0.43

+ +Sep 28, 2002 + + + + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/class.html dmd-0.136/dmd/html/d/class.html --- dmd-0.135/dmd/html/d/class.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/class.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,1096 +1,1121 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Classes - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

Classes

- - The object-oriented features of D all come from classes. The class hierarchy - has as its root the class Object. Object defines a minimum level of functionality - that each derived class has, and a default implementation for that functionality. -

- - Classes are programmer defined types. Support for classes are what - make D an object oriented language, giving it encapsulation, inheritance, - and polymorphism. D classes support the single inheritance paradigm, extended - by adding support for interfaces. Class objects are instantiated by reference - only. -

- - A class can be exported, which means its name and all its non-private - members are exposed externally to the DLL or EXE. -

- - A class declaration is defined: - -

-	ClassDeclaration:
-		class Identifier BaseClassListopt ClassBody
-
-	BaseClassList:
-		: SuperClass
-		: SuperClass InterfaceClasses
-		: InterfaceClass
-		: InterfaceClass InterfaceClasses
-
-	SuperClass:
-		Identifier
-		Protection Identifier
-
-	InterfaceClasses:
-		InterfaceClass
-		InterfaceClass InterfaceClasses
-
-	InterfaceClass:
-		Identifier
-		Protection Identifier
-
-	Protection:
-		private
-		package
-		public
-		export
-
-	ClassBody:
-		{ }
-		{ ClassBodyDeclarations }
-
-	ClassBodyDeclarations:
-		ClassBodyDeclaration
-		ClassBodyDeclaration ClassBodyDeclarations
-
-	ClassBodyDeclaration:
-		Declaration
-		Constructor
-		Destructor
-		StaticConstructor
-		StaticDestructor
-		Invariant
-		UnitTest
-		ClassAllocator
-		ClassDeallocator
-	
- -Classes consist of: - -
-
super class -
interfaces -
dynamic fields -
static fields -
types -
functions -
-
-
static functions -
dynamic functions -
constructors -
destructors -
static constructors -
static destructors -
invariants -
unit tests -
allocators -
deallocators -
-
-
- - A class is defined: - -
-	class Foo
-	{
-	    ... members ...
-	}
-	
- - Note that there is no trailing ; after the closing } of the class - definition. - It is also not possible to declare a variable var like: - -
-	class Foo { } var;
-	
- - Instead: - -
-	class Foo { }
-	Foo var;
-	
- -

Fields

- - Class members are always accessed with the . operator. There are no :: or -> - operators as in C++. -

- - The D compiler is free to rearrange the order of fields in a class to - optimally pack them in an implementation-defined manner. - Consider the fields much like the local - variables in a function - - the compiler assigns some to registers and shuffles others around all to - get the optimal - stack frame layout. This frees the code designer to organize the fields - in a manner that - makes the code more readable rather than being forced to organize it - according to - machine optimization rules. Explicit control of field layout is provided - by struct/union - types, not classes. - -

Field Properties

- - The .offsetof property gives the offset in bytes of the field - from the beginning of the class instantiation. - .offsetof can only be applied to fields qualified with the - type of the class, not expressions which produce the type of - the field itself: - -
-	class Foo
-	{
-	    int x;
-	}
-	...
-	void test(Foo foo)
-	{
-	    size_t o;
-
-	    o = Foo.x.offsetof;   // yields 8
-	    o = foo.x.offsetof;   // error, .offsetof an int type
-	}
-	
- -

Super Class

- - All classes inherit from a super class. If one is not specified, - it inherits from Object. Object forms the root of the D class - inheritance hierarchy. - -

Constructors

- -
-	Constructor:
-		this( ParameterList ) BlockStatement
-	
- - Members are always initialized to the default initializer - for their type, which is usually 0 for integer types and - NAN for floating point types. - This eliminates an entire - class of obscure problems that come from - neglecting to initialize a member in one of the constructors. - In the class definition, - there can be a static initializer to be - used instead of the default: - -
-	class Abc
-	{
-	    int a;	// default initializer for a is 0
-	    long b = 7;	// default initializer for b is 7
-	    float f;	// default initializer for f is NAN
-	}
-	
- - This static initialization is done before any constructors are - called. -

- - Constructors are defined with a function name of this - and having no return value: - -

-	class Foo
-	{
-	    this(int x)		// declare constructor for Foo
-	    {   ...
-	    }
-	    this()
-	    {   ...
-	    }
-	}
-	
- - Base class construction is done by calling the base class - constructor by the name super: - -
-	class A { this(int y) { } }
-
-	class B : A
-	{
-	    int j;
-	    this()
-	    {
-		...
-		super(3);	// call base constructor A.this(3)
-		...
-	    }
-	}
-	
- - Constructors can also call other constructors for the same class - in order to share common initializations: - -
-	class C
-	{
-	    int j;
-	    this()
-	    {
-		...
-	    }
-	    this(int i)
-	    {
-		this();
-		j = i;
-	    }
-	}
-	
- - If no call to constructors via this or super appear - in a constructor, and the base class has a constructor, a call - to super() is inserted at the beginning of the constructor. -

- - If there is no constructor for a class, but there is a constructor - for the base class, a default constructor of the form: - -

-	this() { }
-	
- - is implicitly generated. -

- - Class object construction is very flexible, but some restrictions - apply: -

    -
  1. It is illegal for constructors to mutually call each other: - -
    -	this() { this(1); }
    -	this(int i) { this(); }	// illegal, cyclic constructor calls
    -	
    - -
  2. If any constructor call appears inside a constructor, any - path through the constructor must make exactly one constructor - call: - -
    -	this()	{ a || super(); }	// illegal
    -
    -	this() { this(1) || super(); }	// ok
    -
    -	this()
    -	{
    -	    for (...)
    -	    {
    -		super();	// illegal, inside loop
    -	    }
    -	}
    -	
    - -
  3. It is illegal to refer to this implicitly or explicitly - prior to making a constructor call. -
  4. Constructor calls cannot appear after labels (in order to make - it easy to check for the previous conditions in the presence of goto's). -
- - Instances of class objects are created with NewExpressions: - -
-	A a = new A(3);
-	
- - The following steps happen: - -
    -
  1. Storage is allocated for the object. - If this fails, rather than return null, an - OutOfMemoryException is thrown. - Thus, tedious checks for null references are unnecessary. - -
  2. The raw data is statically initialized using the values provided - in the class definition. - The pointer to the vtbl is assigned. - This ensures that constructors are - passed fully formed objects. - This operation is equivalent to doing a memcpy() of a static - version of the object onto the newly allocated one, - although more advanced compilers - may be able to optimize much of this away. - -
  3. If there is a constructor defined for the class, - the constructor matching the - argument list is called. - -
  4. If class invariant checking is turned on, the class invariant - is called at the end of the constructor. -
- -

Destructors

- -
-	Destructor:
-		~this() BlockStatement
-	
- - The garbage collector calls the destructor function when the object - is deleted. The syntax - is: - -
-	class Foo
-	{
-		~this()		// destructor for Foo
-		{
-		}
-	}
-	
- - There can be only one destructor per class, the destructor - does not have any parameters, - and has no attributes. It is always virtual. -

- - The destructor is expected to release any resources held by the object. -

- - The program can explicitly inform the garbage collector that an - object is no longer referred to (with the delete expression), and - then the garbage collector calls the destructor - immediately, and adds the object's memory to the free storage. - The destructor is guaranteed to never be called twice. -

- - The destructor for the super class automatically gets called when - the destructor ends. There is no way to call the super destructor - explicitly. -

- - When the garbage collector calls a destructor for an object of a class - that has - members that are references to garbage collected objects, those - references are no longer valid. This means that destructors - cannot reference sub objects. - This rule does not apply to auto objects or objects deleted - with the DeleteExpression. -

- - The garbage collector is not guaranteed to run the destructor - for all unreferenced objects. Furthermore, the order in which the - garbage collector calls destructors for unreference objects - is not specified. -

- - Objects referenced from the data segment never get collected - by the gc. - -

Static Constructors

- -
-	StaticConstructor:
-		static this() BlockStatement
-	
- - A static constructor is defined as a function that performs - initializations before the - main() function gets control. Static constructors are used to - initialize - static class members - with values that cannot be computed at compile time. -

- - Static constructors in other languages are built implicitly by using - member - initializers that can't be computed at compile time. The trouble with - this stems from not - having good control over exactly when the code is executed, for example: - -

-	class Foo
-	{
-	    static int a = b + 1;
-	    static int b = a * 2;
-	}
-	
- - What values do a and b end up with, what order are the initializations - executed in, what - are the values of a and b before the initializations are run, is this a - compile error, or is this - a runtime error? Additional confusion comes from it not being obvious if - an initializer is - static or dynamic. -

- - D makes this simple. All member initializations must be determinable by - the compiler at - compile time, hence there is no order-of-evaluation dependency for - member - initializations, and it is not possible to read a value that has not - been initialized. Dynamic - initialization is performed by a static constructor, defined with - a special syntax static this(). - -

-	class Foo
-	{
-	    static int a;		// default initialized to 0
-	    static int b = 1;
-	    static int c = b + a;	// error, not a constant initializer
-
-	    static this()		// static constructor
-	    {
-		a = b + 1;		// a is set to 2
-		b = a * 2;		// b is set to 4
-	    }
-	}
-	
- - static this() is called by the startup code before - main() is called. If it returns normally - (does not throw an exception), the static destructor is added - to the list of functions to be - called on program termination. - Static constructors have empty parameter lists. -

- - Static constructors within a module are executed in the lexical - order in which they appear. - All the static constructors for modules that are directly or - indirectly imported - are executed before the static constructors for the importer. -

- - The static in the static constructor declaration is not - an attribute, it must appear immediately before the this: - -

-	class Foo
-	{
-	    static this() { ... }	// a static constructor
-	    static private this() { ... } // not a static constructor
-	    static
-	    {
-		this() { ... }		// not a static constructor
-	    }
-	    static:
-		this() { ... }		// not a static constructor
-	}
-	
- -

Static Destructor

- -
-	StaticDestructor:
-		static ~this() BlockStatement
-	
- - A static destructor is defined as a special static function with the - syntax static ~this(). - -
-	class Foo
-	{
-	    static ~this()		// static destructor
-	    {
-	    }
-	}
-	
- - A static destructor gets called on program termination, but only if - the static constructor - completed successfully. - Static destructors have empty parameter lists. - Static destructors get called in the reverse order that the static - constructors were called in. -

- - The static in the static denstructor declaration is not - an attribute, it must appear immediately before the ~this: - -

-	class Foo
-	{
-	    static ~this() { ... }	// a static destructor
-	    static private ~this() { ... } // not a static destructor
-	    static
-	    {
-		~this() { ... }		// not a static destructor
-	    }
-	    static:
-		~this() { ... }		// not a static destructor
-	}
-	
- -

Class Invariants

- -
-	ClassInvariant:
-		invariant BlockStatement
-	
- - Class invariants are used to specify characteristics of a class that always - must be true (except while executing a member function). For example, a - class representing a date might have an invariant that the day must be 1..31 - and the hour must be 0..23: - - - -
-	class Date
-	{
-	    int day;
-	    int hour;
-
-	    invariant
-	    {
-		assert(1 <= day && day <= 31);
-		assert(0 <= hour && hour < 24);
-	    }
-	}
-	
- - The class invariant is a contract saying that the asserts must hold - true. - The invariant is checked when a class constructor completes, - at the start of the class destructor, before a public or exported - member is run, and after a public or exported function finishes. -

- - The code in the invariant may not call any public non-static members - of the - class, either directly or indirectly. - Doing so will result in a stack overflow, as the invariant will wind - up being called in an infinitely recursive manner. - -

-	class Foo
-	{
-	    public void f() { }
-	    private void g() { }
-
-	    invariant
-	    {
-		f();  // error, cannot call public member function from invariant
-		g();  // ok, g() is not public
-	    }
-	}
-	
- - The invariant - can be checked when a class object is the argument to an - assert() expression, as: - -
-	Date mydate;
-	...
-	assert(mydate);		// check that class Date invariant holds
-	
- - If the invariant fails, it throws an InvariantException. - Class invariants are inherited, that is, - any class invariant is implicitly anded with the invariants of its base classes. -

- - There can be only one ClassInvariant per class. -

- - When compiling for release, the invariant code is not generated, and the compiled program - runs at maximum speed. - -

Unit Tests

- -
-	UnitTest:
-		unittest BlockStatement
-	
- - Unit tests are a series of test cases applied to a class to determine - if it is working properly. Ideally, unit tests should be run every - time a program is compiled. The best way to make sure that unit - tests do get run, and that they are maintained along with the class - code is to put the test code right in with the class implementation - code. -

- - Classes can have a special member function called: - -

-	unittest
-	{
-	    ...test code...
-	}
-	
- - A compiler switch, such as -unittest for dmd, will - cause the unittest test code to be compiled and incorporated into - the resulting executable. The unittest code gets run after - static initialization is run and before the main() - function is called. -

- - For example, given a class Sum that is used to add two values: - -

-	class Sum
-	{
-	    int add(int x, int y) { return x + y; }
-
-	    unittest
-	    {
-		Sum sum = new Sum;
-		assert(sum.add(3,4) == 7);
-		assert(sum.add(-2,0) == -2);
-	    }
-	}
-	
- -

Class Allocators

- -
-	ClassAllocator:
-		new ( ParameterList ) BlockStatement
-	
- - A class member function of the form: - -
-	new(uint size)
-	{
-	    ...
-	}
-	
- - is called a class allocator. - The class allocator can have any number of parameters, provided - the first one is of type uint. - Any number can be defined for a class, the correct one is - determined by the usual function overloading rules. - When a new expression: - -
-	new Foo;
-	
- - is executed, and Foo is a class that has - an allocator, the allocator is called with the first argument - set to the size in bytes of the memory to be allocated for the - instance. - The allocator must allocate the memory and return it as a - void*. - If the allocator fails, it must not return a null, but - must throw an exception. - If there is more than one parameter to the allocator, the - additional arguments are specified within parentheses after - the new in the NewExpression: - -
-	class Foo
-	{
-	    this(char[] a) { ... }
-
-	    new(uint size, int x, int y)
-	    {
-		...
-	    }
-	}
-
-	...
-
-	new(1,2) Foo(a);	// calls new(Foo.size,1,2)
-	
- - Derived classes inherit any allocator from their base class, - if one is not specified. -

- - See also Explicit Class Instance Allocation. - -

Class Deallocators

- -
-	ClassDeallocator:
-		delete ( ParameterList ) BlockStatement
-	
- - A class member function of the form: - -
-	delete(void *p)
-	{
-	    ...
-	}
-	
- - is called a class deallocator. - The deallocator must have exactly one parameter of type void*. - Only one can be specified for a class. - When a delete expression: - -
-	delete f;
-	
- - is executed, and f is a reference to a class instance that has - a deallocator, the deallocator is called with a pointer to the - class instance after the destructor (if any) for the class is - called. It is the responsibility of the deallocator to free - the memory. -

- - Derived classes inherit any deallocator from their base class, - if one is not specified. -

- - See also Explicit Class Instance Allocation. - -

Auto Classes

- - An auto class is a class with the auto attribute, as in: - -
-	auto class Foo { ... }
-	
- - The auto characteristic is inherited, so if any classes derived - from an auto class are also auto. -

- - An auto class reference can only appear as a function local variable. - It must be declared as being auto: - -

-	auto class Foo { ... }
-
-	void func()
-	{
-	    Foo f;	// error, reference to auto class must be auto
-	    auto Foo g = new Foo();	// correct
-	}
-	
- - When an auto class reference goes out of scope, the destructor - (if any) for it is automatically called. This holds true even if - the scope was exited via a thrown exception. - -

Nested Classes

- - A nested class is a class that is declared inside the scope - of a function or another class. - A nested class has access to the variables and other symbols - of the classes and functions it is nested inside: - -
-	class Outer
-	{
-	    int m;
-
-	    class Inner
-	    {
-		int foo()
-		{
-		    return m;	// Ok to access member of Outer
-		}
-	    }
-	}
-
-	void func()
-	{   int m;
-
-	    class Inner
-	    {
-		int foo()
-		{
-		    return m;	// Ok to access local variable m of func()
-		}
-	    }
-	}
-	
- - If a nested class has the static attribute, then it can - not access variables of the enclosing scope that are local to the - stack or need a this: - -
-	class Outer
-	{
-	    int m;
-	    static int n;
-
-	    static class Inner
-	    {
-		int foo()
-		{
-		    return m;	// Error, Inner is static and m needs a this
-		    return n;	// Ok, n is static
-		}
-	    }
-	}
-
-	void func()
-	{   int m;
-	    static int n;
-
-	    static class Inner
-	    {
-		int foo()
-		{
-		    return m;	// Error, Inner is static and m is local to the stack
-		    return n;	// Ok, n is static
-		}
-	    }
-	}
-	
- - Non-static nested classes work by containing an extra hidden member - (called the context pointer) - that is the frame pointer of the enclosing function if it is nested - inside a function, or the this of the enclosing class's instance - if it is nested inside a class. -

- - When a non-static nested class is instantiated, the context pointer - is assigned before the class's constructor is called, therefore - the constructor has full access to the enclosing variables. - A non-static nested class can only be instantiated when the necessary - context pointer information is available: - -

-	class Outer
-	{
-	    class Inner { }
-
-	    static class SInner { }
-	}
-
-	void func()
-	{
-	    class Nested { }
-
-	    Outer o = new Outer;	// Ok
-	    Outer.Inner oi = new Outer.Inner;	// Error, no 'this' for Outer
-	    Outer.SInner os = new Outer.SInner;	// Ok
-
-	    Nested n = new Nested;	// Ok
-	}
-	
- - While a non-static nested class can access the stack variables - of its enclosing function, that access becomes invalid once - the enclosing function exits: - -
-	class Base
-	{
-	    int foo() { return 1; }
-	}
-
-	Base func()
-	{   int m = 3;
-
-	    class Nested : Base
-	    {
-		int foo() { return m; }
-	    }
-
-	    Base b = new Nested;
-
-	    assert(b.foo() == 3);	// Ok, func() is still active
-	    return b;
-	}
-
-	int test()
-	{
-	    Base b = func();
-	    return b.foo();		// Error, func().m is undefined
-	}
-	
- - If this kind of functionality is needed, the way to make it work - is to make copies of the needed variables within the nested class's - constructor: - -
-	class Base
-	{
-	    int foo() { return 1; }
-	}
-
-	Base func()
-	{   int m = 3;
-
-	    class Nested : Base
-	    {	int m_;
-
-		this() { m_ = m;
-		int foo() { return m_; }
-	    }
-
-	    Base b = new Nested;
-
-	    assert(b.foo() == 3);	// Ok, func() is still active
-	    return b;
-	}
-
-	int test()
-	{
-	    Base b = func();
-	    return b.foo();		// Ok, using cached copy of func().m
-	}
-	
- -

Anonymous Nested Classes

- - An anonymous nested class is both defined and instantiated with - a NewAnonClassExpression: - -
-	NewAnonClassExpression:
-	    new (ArgumentList)opt class (ArgumentList)opt SuperClassopt InterfaceClassesopt ClassBody
-	
- - which is equivalent to: - -
-	class Identifier : SuperClass InterfaceClasses
-		ClassBody
-
-	new (ArgumentList) Identifier (ArgumentList);
-	
- - where Identifier is the name generated for the anonymous - nested class. - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Classes + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

Classes

+ + The object-oriented features of D all come from classes. The class hierarchy + has as its root the class Object. Object defines a minimum level of functionality + that each derived class has, and a default implementation for that functionality. +

+ + Classes are programmer defined types. Support for classes are what + make D an object oriented language, giving it encapsulation, inheritance, + and polymorphism. D classes support the single inheritance paradigm, extended + by adding support for interfaces. Class objects are instantiated by reference + only. +

+ + A class can be exported, which means its name and all its non-private + members are exposed externally to the DLL or EXE. +

+ + A class declaration is defined: + +

+ClassDeclaration:
+	class Identifier BaseClassListopt ClassBody
+
+BaseClassList:
+	: SuperClass
+	: SuperClass InterfaceClasses
+	: InterfaceClass
+	: InterfaceClass InterfaceClasses
+
+SuperClass:
+	Identifier
+	Protection Identifier
+
+InterfaceClasses:
+	InterfaceClass
+	InterfaceClass InterfaceClasses
+
+InterfaceClass:
+	Identifier
+	Protection Identifier
+
+Protection:
+	private
+	package
+	public
+	export
+
+ClassBody:
+	{ }
+	{ ClassBodyDeclarations }
+
+ClassBodyDeclarations:
+	ClassBodyDeclaration
+	ClassBodyDeclaration ClassBodyDeclarations
+
+ClassBodyDeclaration:
+	Declaration
+	Constructor
+	Destructor
+	StaticConstructor
+	StaticDestructor
+	Invariant
+	UnitTest
+	ClassAllocator
+	ClassDeallocator
+
+ + +Classes consist of: + +
+
super class +
interfaces +
dynamic fields +
static fields +
types +
functions +
+
+
static functions +
dynamic functions +
constructors +
destructors +
static constructors +
static destructors +
invariants +
unit tests +
allocators +
deallocators +
+
+
+ + A class is defined: + +
class Foo
+{
+    ... members ...
+}
+
+ + Note that there is no trailing ; after the closing } of the class + definition. + It is also not possible to declare a variable var like: + +
class Foo { } var;
+
+ + Instead: + +
class Foo { }
+Foo var;
+
+ +

Fields

+ + Class members are always accessed with the . operator. There are no :: or -> + operators as in C++. +

+ + The D compiler is free to rearrange the order of fields in a class to + optimally pack them in an implementation-defined manner. + Consider the fields much like the local + variables in a function - + the compiler assigns some to registers and shuffles others around all to + get the optimal + stack frame layout. This frees the code designer to organize the fields + in a manner that + makes the code more readable rather than being forced to organize it + according to + machine optimization rules. Explicit control of field layout is provided + by struct/union + types, not classes. + +

Field Properties

+ + The .offsetof property gives the offset in bytes of the field + from the beginning of the class instantiation. + .offsetof can only be applied to fields qualified with the + type of the class, not expressions which produce the type of + the field itself: + +
class Foo
+{
+    int x;
+}
+...
+void test(Foo foo)
+{
+    size_t o;
+
+    o = Foo.x.offsetof;   // yields 8
+    o = foo.x.offsetof;   // error, .offsetof an int type
+}
+
+ +

Super Class

+ + All classes inherit from a super class. If one is not specified, + it inherits from Object. Object forms the root of the D class + inheritance hierarchy. + +

Constructors

+ +
+Constructor:
+	this ( ParameterList ) BlockStatement
+
+ + + Members are always initialized to the default initializer + for their type, which is usually 0 for integer types and + NAN for floating point types. + This eliminates an entire + class of obscure problems that come from + neglecting to initialize a member in one of the constructors. + In the class definition, + there can be a static initializer to be + used instead of the default: + +
class Abc
+{
+    int a;	// default initializer for a is 0
+    long b = 7;	// default initializer for b is 7
+    float f;	// default initializer for f is NAN
+}
+
+ + This static initialization is done before any constructors are + called. +

+ + Constructors are defined with a function name of this + and having no return value: + +

class Foo
+{
+    this(int x)		// declare constructor for Foo
+    {   ...
+    }
+    this()
+    {   ...
+    }
+}
+
+ + Base class construction is done by calling the base class + constructor by the name super: + +
class A { this(int y) { } }
+
+class B : A
+{
+    int j;
+    this()
+    {
+	...
+	super(3);	// call base constructor A.this(3)
+	...
+    }
+}
+
+ + Constructors can also call other constructors for the same class + in order to share common initializations: + +
class C
+{
+    int j;
+    this()
+    {
+	...
+    }
+    this(int i)
+    {
+	this();
+	j = i;
+    }
+}
+
+ + If no call to constructors via this or super appear + in a constructor, and the base class has a constructor, a call + to super() is inserted at the beginning of the constructor. +

+ + If there is no constructor for a class, but there is a constructor + for the base class, a default constructor of the form: + +

this() { }
+
+ + is implicitly generated. +

+ + Class object construction is very flexible, but some restrictions + apply: +

    +
  1. It is illegal for constructors to mutually call each other: + +
    this() { this(1); }
    +this(int i) { this(); }	// illegal, cyclic constructor calls
    +
    + +
  2. If any constructor call appears inside a constructor, any + path through the constructor must make exactly one constructor + call: + +
    this()	{ a || super(); }	// illegal
    +
    +this() { this(1) || super(); }	// ok
    +
    +this()
    +{
    +    for (...)
    +    {
    +	super();	// illegal, inside loop
    +    }
    +}
    +
    + +
  3. It is illegal to refer to this implicitly or explicitly + prior to making a constructor call. +
  4. Constructor calls cannot appear after labels (in order to make + it easy to check for the previous conditions in the presence of goto's). +
+ + Instances of class objects are created with NewExpressions: + +
A a = new A(3);
+
+ + The following steps happen: + +
    +
  1. Storage is allocated for the object. + If this fails, rather than return null, an + OutOfMemoryException is thrown. + Thus, tedious checks for null references are unnecessary. + +
  2. The raw data is statically initialized using the values provided + in the class definition. + The pointer to the vtbl is assigned. + This ensures that constructors are + passed fully formed objects. + This operation is equivalent to doing a memcpy() of a static + version of the object onto the newly allocated one, + although more advanced compilers + may be able to optimize much of this away. + +
  3. If there is a constructor defined for the class, + the constructor matching the + argument list is called. + +
  4. If class invariant checking is turned on, the class invariant + is called at the end of the constructor. +
+ +

Destructors

+ +
+Destructor:
+	~this() BlockStatement
+
+ + + The garbage collector calls the destructor function when the object + is deleted. The syntax + is: + +
class Foo
+{
+	~this()		// destructor for Foo
+	{
+	}
+}
+
+ + There can be only one destructor per class, the destructor + does not have any parameters, + and has no attributes. It is always virtual. +

+ + The destructor is expected to release any resources held by the object. +

+ + The program can explicitly inform the garbage collector that an + object is no longer referred to (with the delete expression), and + then the garbage collector calls the destructor + immediately, and adds the object's memory to the free storage. + The destructor is guaranteed to never be called twice. +

+ + The destructor for the super class automatically gets called when + the destructor ends. There is no way to call the super destructor + explicitly. +

+ + When the garbage collector calls a destructor for an object of a class + that has + members that are references to garbage collected objects, those + references are no longer valid. This means that destructors + cannot reference sub objects. + This rule does not apply to auto objects or objects deleted + with the DeleteExpression. +

+ + The garbage collector is not guaranteed to run the destructor + for all unreferenced objects. Furthermore, the order in which the + garbage collector calls destructors for unreference objects + is not specified. +

+ + Objects referenced from the data segment never get collected + by the gc. + +

Static Constructors

+ +
+StaticConstructor:
+	static this() BlockStatement
+
+ + + A static constructor is defined as a function that performs + initializations before the + main() function gets control. Static constructors are used to + initialize + static class members + with values that cannot be computed at compile time. +

+ + Static constructors in other languages are built implicitly by using + member + initializers that can't be computed at compile time. The trouble with + this stems from not + having good control over exactly when the code is executed, for example: + +

class Foo
+{
+    static int a = b + 1;
+    static int b = a * 2;
+}
+
+ + What values do a and b end up with, what order are the initializations + executed in, what + are the values of a and b before the initializations are run, is this a + compile error, or is this + a runtime error? Additional confusion comes from it not being obvious if + an initializer is + static or dynamic. +

+ + D makes this simple. All member initializations must be determinable by + the compiler at + compile time, hence there is no order-of-evaluation dependency for + member + initializations, and it is not possible to read a value that has not + been initialized. Dynamic + initialization is performed by a static constructor, defined with + a special syntax static this(). + +

class Foo
+{
+    static int a;		// default initialized to 0
+    static int b = 1;
+    static int c = b + a;	// error, not a constant initializer
+
+    static this()		// static constructor
+    {
+	a = b + 1;		// a is set to 2
+	b = a * 2;		// b is set to 4
+    }
+}
+
+ + static this() is called by the startup code before + main() is called. If it returns normally + (does not throw an exception), the static destructor is added + to the list of functions to be + called on program termination. + Static constructors have empty parameter lists. +

+ + Static constructors within a module are executed in the lexical + order in which they appear. + All the static constructors for modules that are directly or + indirectly imported + are executed before the static constructors for the importer. +

+ + The static in the static constructor declaration is not + an attribute, it must appear immediately before the this: + +

class Foo
+{
+    static this() { ... }	// a static constructor
+    static private this() { ... } // not a static constructor
+    static
+    {
+	this() { ... }		// not a static constructor
+    }
+    static:
+	this() { ... }		// not a static constructor
+}
+
+ +

Static Destructor

+ +
+StaticDestructor:
+	static ~this() BlockStatement
+
+ + + A static destructor is defined as a special static function with the + syntax static ~this(). + +
class Foo
+{
+    static ~this()		// static destructor
+    {
+    }
+}
+
+ + A static destructor gets called on program termination, but only if + the static constructor + completed successfully. + Static destructors have empty parameter lists. + Static destructors get called in the reverse order that the static + constructors were called in. +

+ + The static in the static denstructor declaration is not + an attribute, it must appear immediately before the ~this: + +

class Foo
+{
+    static ~this() { ... }	// a static destructor
+    static private ~this() { ... } // not a static destructor
+    static
+    {
+	~this() { ... }		// not a static destructor
+    }
+    static:
+	~this() { ... }		// not a static destructor
+}
+
+ +

Class Invariants

+ +
+ClassInvariant:
+	invariant BlockStatement
+
+ + + Class invariants are used to specify characteristics of a class that always + must be true (except while executing a member function). For example, a + class representing a date might have an invariant that the day must be 1..31 + and the hour must be 0..23: + + + +
class Date
+{
+    int day;
+    int hour;
+
+    invariant
+    {
+	assert(1 <= day && day <= 31);
+	assert(0 <= hour && hour < 24);
+    }
+}
+
+ + The class invariant is a contract saying that the asserts must hold + true. + The invariant is checked when a class constructor completes, + at the start of the class destructor, before a public or exported + member is run, and after a public or exported function finishes. +

+ + The code in the invariant may not call any public non-static members + of the + class, either directly or indirectly. + Doing so will result in a stack overflow, as the invariant will wind + up being called in an infinitely recursive manner. + +

class Foo
+{
+    public void f() { }
+    private void g() { }
+
+    invariant
+    {
+	f();  // error, cannot call public member function from invariant
+	g();  // ok, g() is not public
+    }
+}
+
+ + The invariant + can be checked when a class object is the argument to an + assert() expression, as: + +
Date mydate;
+...
+assert(mydate);		// check that class Date invariant holds
+
+ + If the invariant fails, it throws an InvariantException. + Class invariants are inherited, that is, + any class invariant is implicitly anded with the invariants of its base classes. +

+ + There can be only one ClassInvariant per class. +

+ + When compiling for release, the invariant code is not generated, and the compiled program + runs at maximum speed. + +

Unit Tests

+ +
+UnitTest:
+	unittest BlockStatement
+
+ + + Unit tests are a series of test cases applied to a class to determine + if it is working properly. Ideally, unit tests should be run every + time a program is compiled. The best way to make sure that unit + tests do get run, and that they are maintained along with the class + code is to put the test code right in with the class implementation + code. +

+ + Classes can have a special member function called: + +

unittest
+{
+    ...test code...
+}
+
+ + A compiler switch, such as -unittest for dmd, will + cause the unittest test code to be compiled and incorporated into + the resulting executable. The unittest code gets run after + static initialization is run and before the main() + function is called. +

+ + For example, given a class Sum that is used to add two values: + +

class Sum
+{
+    int add(int x, int y) { return x + y; }
+
+    unittest
+    {
+	Sum sum = new Sum;
+	assert(sum.add(3,4) == 7);
+	assert(sum.add(-2,0) == -2);
+    }
+}
+
+ +

Class Allocators

+ +
+ClassAllocator:
+	new () ParameterList  BlockStatement
+
+ + + A class member function of the form: + +
new(uint size)
+{
+    ...
+}
+
+ + is called a class allocator. + The class allocator can have any number of parameters, provided + the first one is of type uint. + Any number can be defined for a class, the correct one is + determined by the usual function overloading rules. + When a new expression: + +
new Foo;
+
+ + is executed, and Foo is a class that has + an allocator, the allocator is called with the first argument + set to the size in bytes of the memory to be allocated for the + instance. + The allocator must allocate the memory and return it as a + void*. + If the allocator fails, it must not return a null, but + must throw an exception. + If there is more than one parameter to the allocator, the + additional arguments are specified within parentheses after + the new in the NewExpression: + +
class Foo
+{
+    this(char[] a) { ... }
+
+    new(uint size, int x, int y)
+    {
+	...
+    }
+}
+
+...
+
+new(1,2) Foo(a);	// calls new(Foo.size,1,2)
+
+ + Derived classes inherit any allocator from their base class, + if one is not specified. +

+ + See also Explicit Class Instance Allocation. + +

Class Deallocators

+ +
+ClassDeallocator:
+	delete () ParameterList  BlockStatement
+
+ + + A class member function of the form: + +
delete(void *p)
+{
+    ...
+}
+
+ + is called a class deallocator. + The deallocator must have exactly one parameter of type void*. + Only one can be specified for a class. + When a delete expression: + +
delete f;
+
+ + is executed, and f is a reference to a class instance that has + a deallocator, the deallocator is called with a pointer to the + class instance after the destructor (if any) for the class is + called. It is the responsibility of the deallocator to free + the memory. +

+ + Derived classes inherit any deallocator from their base class, + if one is not specified. +

+ + See also Explicit Class Instance Allocation. + +

Auto Classes

+ + An auto class is a class with the auto attribute, as in: + +
auto class Foo { ... }
+
+ + The auto characteristic is inherited, so if any classes derived + from an auto class are also auto. +

+ + An auto class reference can only appear as a function local variable. + It must be declared as being auto: + +

auto class Foo { ... }
+
+void func()
+{
+    Foo f;	// error, reference to auto class must be auto
+    auto Foo g = new Foo();	// correct
+}
+
+ + When an auto class reference goes out of scope, the destructor + (if any) for it is automatically called. This holds true even if + the scope was exited via a thrown exception. + +

Nested Classes

+ + A nested class is a class that is declared inside the scope + of a function or another class. + A nested class has access to the variables and other symbols + of the classes and functions it is nested inside: + +
class Outer
+{
+    int m;
+
+    class Inner
+    {
+	int foo()
+	{
+	    return m;	// Ok to access member of Outer
+	}
+    }
+}
+
+void func()
+{   int m;
+
+    class Inner
+    {
+	int foo()
+	{
+	    return m;	// Ok to access local variable m of func()
+	}
+    }
+}
+
+ + If a nested class has the static attribute, then it can + not access variables of the enclosing scope that are local to the + stack or need a this: + +
class Outer
+{
+    int m;
+    static int n;
+
+    static class Inner
+    {
+	int foo()
+	{
+	    return m;	// Error, Inner is static and m needs a this
+	    return n;	// Ok, n is static
+	}
+    }
+}
+
+void func()
+{   int m;
+    static int n;
+
+    static class Inner
+    {
+	int foo()
+	{
+	    return m;	// Error, Inner is static and m is local to the stack
+	    return n;	// Ok, n is static
+	}
+    }
+}
+
+ + Non-static nested classes work by containing an extra hidden member + (called the context pointer) + that is the frame pointer of the enclosing function if it is nested + inside a function, or the this of the enclosing class's instance + if it is nested inside a class. +

+ + When a non-static nested class is instantiated, the context pointer + is assigned before the class's constructor is called, therefore + the constructor has full access to the enclosing variables. + A non-static nested class can only be instantiated when the necessary + context pointer information is available: + +

class Outer
+{
+    class Inner { }
+
+    static class SInner { }
+}
+
+void func()
+{
+    class Nested { }
+
+    Outer o = new Outer;	// Ok
+    Outer.Inner oi = new Outer.Inner;	// Error, no 'this' for Outer
+    Outer.SInner os = new Outer.SInner;	// Ok
+
+    Nested n = new Nested;	// Ok
+}
+
+ + While a non-static nested class can access the stack variables + of its enclosing function, that access becomes invalid once + the enclosing function exits: + +
class Base
+{
+    int foo() { return 1; }
+}
+
+Base func()
+{   int m = 3;
+
+    class Nested : Base
+    {
+	int foo() { return m; }
+    }
+
+    Base b = new Nested;
+
+    assert(b.foo() == 3);	// Ok, func() is still active
+    return b;
+}
+
+int test()
+{
+    Base b = func();
+    return b.foo();		// Error, func().m is undefined
+}
+
+ + If this kind of functionality is needed, the way to make it work + is to make copies of the needed variables within the nested class's + constructor: + +
class Base
+{
+    int foo() { return 1; }
+}
+
+Base func()
+{   int m = 3;
+
+    class Nested : Base
+    {   int m_;
+
+	this() { m_ = m;
+	int foo() { return m_; }
+    }
+
+    Base b = new Nested;
+
+    assert(b.foo() == 3);	// Ok, func() is still active
+    return b;
+}
+
+int test()
+{
+    Base b = func();
+    return b.foo();		// Ok, using cached copy of func().m
+}
+
+ +

Anonymous Nested Classes

+ + An anonymous nested class is both defined and instantiated with + a NewAnonClassExpression: + +
+NewAnonClassExpression:
+    new ()ArgumentListopt class ()ArgumentListopt SuperClassopt InterfaceClassesopt ClassBody
+
+ + + which is equivalent to: + +
class Identifier : SuperClass InterfaceClasses
+	ClassBody
+
+new (ArgumentList) Identifier (ArgumentList);
+
+ + where Identifier is the name generated for the anonymous + nested class. + + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/comparison.html dmd-0.136/dmd/html/d/comparison.html --- dmd-0.135/dmd/html/d/comparison.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/comparison.html 2005-10-17 00:39:32.000000000 +0200 @@ -1,903 +1,912 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Digital Mars - The D Programming Language - Comparison - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- -D vs C/C++/C#/Java

-Rationale for Builtins

-Converting C to D

-Converting C++ to D

-The C Preprocessor vs D

-D strings vs C++ std::string

-D complex vs C++ std::complex

-D Contract Programming vs C++

-
-
- - -

D vs Other Languages

- - This table is a quick and rough comparison of various features of - D - with other languages it is frequently compared with. - While many capabilities are available with standard libraries, this - table is for features built in to the core language itself. - Rationale. - Only official standardized features are considered, not proposed - features, betas, or extensions. And, like all language comparisons, - it is biased in terms of what features are mentioned, omitted, and - my interpretation of those features. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Feature - D - C - C++ - C# - Java -
Garbage Collection - Yes - No - No - Yes - Yes - -
Functions - - - - - - -
Function delegates - Yes - No - No - Yes - No - -
Function overloading - Yes - No - Yes - Yes - Yes - -
Out function parameters - Yes - Yes - Yes - Yes - No - -
Nested functions - Yes - No - No - No - No - -
Function literals - Yes - No - No - No - No - -
Dynamic closures - Yes - No - No - No - No - -
Typesafe variadic arguments - Yes - No - No - Yes - Yes - -
Arrays - - - - - - -
Lightweight arrays - Yes - Yes - Yes - No - No - -
Resizeable arrays - Yes - No - No - No - No - -
Arrays of bits - Yes - No - No - No - No - -
Built-in strings - Yes - No - No - Yes - Yes - -
Array slicing - Yes - No - No - No - No - -
Array bounds checking - Yes - No - No - Yes - Yes - -
Associative arrays - Yes - No - No - No - No - -
Strong typedefs - Yes - No - No - No - No - -
String switches - Yes - No - No - Yes - No - -
Aliases - Yes - Yes - Yes - No - No - -
OOP - - - - - - -
Object Oriented - Yes - No - Yes - Yes - Yes - -
Multiple Inheritance - No - No - Yes - No - No - -
Interfaces - Yes - No - Yes - Yes - Yes - -
Operator overloading - Yes - No - Yes - Yes - No - -
Modules - Yes - No - Yes - Yes - Yes - -
Dynamic class loading - No - No - No - Yes - Yes - -
Nested classes - Yes - Yes - Yes - Yes - Yes - -
Inner (adaptor) classes - Yes - No - No - No - Yes - -
Covariant return types - Yes - No - Yes - No - Yes - -
Properties - Yes - No - No - Yes - No - -
Performance - - - - - - -
Inline assembler - Yes - Yes - Yes - No - No - -
Direct access to hardware - Yes - Yes - Yes - No - No - -
Lightweight objects - Yes - Yes - Yes - Yes - No - -
Explicit memory allocation control - Yes - Yes - Yes - No - No - -
Independent of VM - Yes - Yes - Yes - No - No - -
Direct native code gen - Yes - Yes - Yes - No - No - -
Generic Programming - - - - - - -
Class Templates - Yes - No - Yes - Yes - Yes - -
Function Templates - Yes - No - Yes - No - Yes - -
Implicit Function Template Instantiation - No - No - Yes - No - No - -
Partial and Explicit Specialization - Yes - No - Yes - No - No - -
Value Template Parameters - Yes - No - Yes - No - No - -
Template Template Parameters - Yes - No - Yes - No - No - -
Mixins - Yes - No - No - No - No - -
static if - Yes - No - No - No - No - -
is expressions - Yes - No - No - No - No - -
typeof - Yes - No - No - Yes - No - -
foreach - Yes - No - No - Yes - Yes - -
Reliability - - - - - - -
Contract Programming - Yes - No - No - No - No - -
Unit testing - Yes - No - No - No - No - -
Static construction order - Yes - No - No - Yes - Yes - -
Guaranteed initialization - Yes - No - No - Yes - Yes - -
RAII (automatic destructors) - Yes - No - Yes - Yes - No - -
Exception handling - Yes - No - Yes - Yes - Yes - -
try-catch-finally blocks - Yes - No - No - Yes - Yes - -
Thread synchronization primitives - Yes - No - No - Yes - Yes - -
Compatibility - - - - - - -
C-style syntax - Yes - Yes - Yes - Yes - Yes - -
Enumerated types - Yes - Yes - Yes - Yes - Yes - -
Support all C types - Yes - Yes - No - No - No - -
80 bit floating point - Yes - Yes - Yes - No - No - -
Complex and Imaginary - Yes - Yes - No - No - No - -
Direct access to C - Yes - Yes - Yes - No - No - -
Use existing debuggers - Yes - Yes - Yes - No - No - -
Struct member alignment control - Yes - No - No - No - No - -
Generates standard object files - Yes - Yes - Yes - No - No - -
Macro text preprocessor - No - Yes - Yes - No - No - -
Other - - - - - - -
Conditional compilation - Yes - Yes - Yes - Yes - No - -
Unicode source text - Yes - Yes - Yes - Yes - Yes - -
Documentation comments - Yes - No - No - Yes - Yes - -
- -

Notes

- -
- -
C Language Specification -
ANSI/ISO/IEC 9899-1999 (a.k.a. C99) -

- -

C++ Language Specification -
ISO/IEC 14882-1998 (a.k.a. C++98) -

- -

C# Language Specification -
ECMA-334 -

- -

Java Language Specification -
"The Java Language Specification" by Gosling, Joy, and Steele, - Addison-Wesley, ISBN 0-201-63451-1 -

- -

Object Oriented -
This means support for classes, member functions, - inheritance, and virtual function dispatch. -

- -

Inline assembler -
Many C and C++ compilers support an inline assembler, but - this is not a standard part of the language, and implementations - vary widely in syntax and quality. -

- -

Interfaces -
Support in C++ for interfaces is weak enough that an - IDL (Interface Description Language) was invented to compensate. -

- -

Modules -
Many correctly argue that C++ doesn't really have modules. - But C++ namespaces coupled with header files share many features - with modules. -

- -

Garbage Collection -
The Hans-Boehm garbage collector can be successfully used - with C and C++, but it is not a standard part of the language. -

- -

Contract Programming -
The Digital Mars C++ compiler supports - Contract Programming - as an extension. - Compare some C++ techniques for - doing Contract Programming with D. -

- -

Resizeable arrays -
Part of the standard library for C++ implements resizeable - arrays, however, they are not part of the core language. - A conforming freestanding implementation of C++ (C++98 17.4.1.3) does - not need to provide these libraries. -

- -

Built-in Strings -
Part of the standard library for C++ implements strings, - however, they are not part of the core language. - A conforming freestanding implementation of C++ (C++98 17.4.1.3) does - not need to provide these libraries. - Here's a comparison of C++ strings - and D built-in strings. -

- -

Strong typedefs -
Strong typedefs can be emulated in C/C++ by wrapping a type - in a struct. Getting this to work right requires much tedious - programming, and so is considered as not supported. -

- -

Use existing debuggers -
By this is meant using common debuggers that can operate - using debug data in common formats embedded in the executable. - A specialized debugger useful only with that language is not required. -

- -

Struct member alignment control -
Although many C/C++ compilers contain pragmas to specify - struct alignment, these are nonstandard and incompatible from - compiler to compiler.
- The C# standard ECMA-334 25.5.8 says only this about struct member - alignment: - "The order in which members are packed - into a struct is unspecified. For alignment purposes, there may be - unnamed padding at the beginning of a struct, within a struct, and at - the end of the struct. The contents of the bits used as padding are - indeterminate." - Therefore, although Microsoft may - have extensions to support specific member alignment, they are not an - official part of standard C#. -

- -

Support all C types -
C99 adds many new types not supported by C++. -

- -

80 bit floating point -
While the standards for C and C++ specify long doubles, few - compilers (besides Digital Mars C/C++) actually implement - 80 bit (or longer) floating point types. -

- -

Mixins -
Mixins have many different meanings in different programming - languages. D mixins mean taking an arbitrary - sequence of declarations - and inserting (mixing) them into the current scope. Mixins can be done - at the global, class, struct, or local level. -

- -

C++ Mixins -
C++ mixins refer to a couple different techniques. The first - is analogous to D's interface classes. The second is to create - a template of the form: -
-	template <class Base> class Mixin : public Base
-	{
-	    ... mixin body ...
-	}
- D mixins are different. -

- -

Static If -
The C and C++ preprocessor directive #if would appear to - be equivalent to the D static if. But there are major and crucial - differences - the #if does not have access to any of the constants, - types, or symbols of the program. It can only access preprocessor - macros. - See this example. -

- -

Is Expressions -
Is expressions enable conditional compilation based - on the characteristics of a type. This is done after a fashion in - C++ using template parameter pattern matching. - See this example - for a comparison of the different approaches. -

- -

Comparison with Ada -
James S. Rogers has written a - comparison chart with Ada. -

- -

Inner (adaptor) classes -
A nested class is one whose definition is within the scope - of another class. An inner class is a nested class that - can also reference the members and fields of the lexically - enclosing class; one can think of it as if it contained a 'this' - pointer to the enclosing class. -

- -

Documentation comments -
Documentation comments refer to a standardized way to produce - documentation from the source code file using specialized - comments. - -
- -

Errors

- - If I've made any errors in this table, please contact me so - I can correct them: - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +Digital Mars - The D Programming Language - Comparison + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Mon Oct 17 00:39:30 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· D vs C/C++/C#/Java
+ + +· Rationale for Builtins
+ + +· Converting C to D
+ + +· Converting C++ to D
+ + +· The C Preprocessor vs D
+ + +· D strings vs C++ std::string
+ + +· D complex vs C++ std::complex
+ + +· D Contract Programming vs C++
+ + +
+
+ +

D + vs Other Languages

+ + This table is a quick and rough comparison of various features of + D + + with other languages it is frequently compared with. + While many capabilities are available with standard libraries, this + table is for features built in to the core language itself. + Rationale. + Only official standardized features are considered, not proposed + features, betas, or extensions. And, like all language comparisons, + it is biased in terms of what features are mentioned, omitted, and + my interpretation of those features. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Feature + D + + C + C++ + C# + Java +
Garbage Collection + Yes + No + No + Yes + Yes + +
Functions + + + + + + +
Function delegates + Yes + No + No + Yes + No + +
Function overloading + Yes + No + Yes + Yes + Yes + +
Out function parameters + Yes + Yes + Yes + Yes + No + +
Nested functions + Yes + No + No + No + No + +
Function literals + Yes + No + No + No + No + +
Dynamic closures + Yes + No + No + No + No + +
Typesafe variadic arguments + Yes + No + No + Yes + Yes + +
Arrays + + + + + + +
Lightweight arrays + Yes + Yes + Yes + No + No + +
Resizeable arrays + Yes + No + No + No + No + +
Arrays of bits + Yes + No + No + No + No + +
Built-in strings + Yes + No + No + Yes + Yes + +
Array slicing + Yes + No + No + No + No + +
Array bounds checking + Yes + No + No + Yes + Yes + +
Associative arrays + Yes + No + No + No + No + +
Strong typedefs + Yes + No + No + No + No + +
String switches + Yes + No + No + Yes + No + +
Aliases + Yes + Yes + Yes + No + No + +
OOP + + + + + + +
Object Oriented + Yes + No + Yes + Yes + Yes + +
Multiple Inheritance + No + No + Yes + No + No + +
Interfaces + Yes + No + Yes + Yes + Yes + +
Operator overloading + Yes + No + Yes + Yes + No + +
Modules + Yes + No + Yes + Yes + Yes + +
Dynamic class loading + No + No + No + Yes + Yes + +
Nested classes + Yes + Yes + Yes + Yes + Yes + +
Inner (adaptor) classes + Yes + No + No + No + Yes + +
Covariant return types + Yes + No + Yes + No + Yes + +
Properties + Yes + No + No + Yes + No + +
Performance + + + + + + +
Inline assembler + Yes + Yes + Yes + No + No + +
Direct access to hardware + Yes + Yes + Yes + No + No + +
Lightweight objects + Yes + Yes + Yes + Yes + No + +
Explicit memory allocation control + Yes + Yes + Yes + No + No + +
Independent of VM + Yes + Yes + Yes + No + No + +
Direct native code gen + Yes + Yes + Yes + No + No + +
Generic Programming + + + + + + +
Class Templates + Yes + No + Yes + Yes + Yes + +
Function Templates + Yes + No + Yes + No + Yes + +
Implicit Function Template Instantiation + No + No + Yes + No + No + +
Partial and Explicit Specialization + Yes + No + Yes + No + No + +
Value Template Parameters + Yes + No + Yes + No + No + +
Template Template Parameters + Yes + No + Yes + No + No + +
Mixins + Yes + No + No + No + No + +
static if + Yes + No + No + No + No + +
is expressions + Yes + No + No + No + No + +
typeof + Yes + No + No + Yes + No + +
foreach + Yes + No + No + Yes + Yes + +
Reliability + + + + + + +
Contract Programming + Yes + No + No + No + No + +
Unit testing + Yes + No + No + No + No + +
Static construction order + Yes + No + No + Yes + Yes + +
Guaranteed initialization + Yes + No + No + Yes + Yes + +
RAII (automatic destructors) + Yes + No + Yes + Yes + No + +
Exception handling + Yes + No + Yes + Yes + Yes + +
try-catch-finally blocks + Yes + No + No + Yes + Yes + +
Thread synchronization primitives + Yes + No + No + Yes + Yes + +
Compatibility + + + + + + +
C-style syntax + Yes + Yes + Yes + Yes + Yes + +
Enumerated types + Yes + Yes + Yes + Yes + Yes + +
Support all C types + Yes + Yes + No + No + No + +
80 bit floating point + Yes + Yes + Yes + No + No + +
Complex and Imaginary + Yes + Yes + No + No + No + +
Direct access to C + Yes + Yes + Yes + No + No + +
Use existing debuggers + Yes + Yes + Yes + No + No + +
Struct member alignment control + Yes + No + No + No + No + +
Generates standard object files + Yes + Yes + Yes + No + No + +
Macro text preprocessor + No + Yes + Yes + No + No + +
Other + + + + + + +
Conditional compilation + Yes + Yes + Yes + Yes + No + +
Unicode source text + Yes + Yes + Yes + Yes + Yes + +
Documentation comments + Yes + No + No + Yes + Yes + +
+ +

Notes

+ +
+ +
C Language Specification +
ANSI/ISO/IEC 9899-1999 (a.k.a. C99) +

+ +

C++ Language Specification +
ISO/IEC 14882-1998 (a.k.a. C++98) +

+ +

C# Language Specification +
ECMA-334 +

+ +

Java Language Specification +
"The Java Language Specification" by Gosling, Joy, and Steele, + Addison-Wesley, ISBN 0-201-63451-1 +

+ +

Object Oriented +
This means support for classes, member functions, + inheritance, and virtual function dispatch. +

+ +

Inline assembler +
Many C and C++ compilers support an inline assembler, but + this is not a standard part of the language, and implementations + vary widely in syntax and quality. +

+ +

Interfaces +
Support in C++ for interfaces is weak enough that an + IDL (Interface Description Language) was invented to compensate. +

+ +

Modules +
Many correctly argue that C++ doesn't really have modules. + But C++ namespaces coupled with header files share many features + with modules. +

+ +

Garbage Collection +
The Hans-Boehm garbage collector can be successfully used + with C and C++, but it is not a standard part of the language. +

+ +

Contract Programming +
The Digital Mars C++ compiler supports + Contract Programming + as an extension. + Compare some C++ techniques for + doing Contract Programming with D. +

+ +

Resizeable arrays +
Part of the standard library for C++ implements resizeable + arrays, however, they are not part of the core language. + A conforming freestanding implementation of C++ (C++98 17.4.1.3) does + not need to provide these libraries. +

+ +

Built-in Strings +
Part of the standard library for C++ implements strings, + however, they are not part of the core language. + A conforming freestanding implementation of C++ (C++98 17.4.1.3) does + not need to provide these libraries. + Here's a comparison of C++ strings + and D built-in strings. +

+ +

Strong typedefs +
Strong typedefs can be emulated in C/C++ by wrapping a type + in a struct. Getting this to work right requires much tedious + programming, and so is considered as not supported. +

+ +

Use existing debuggers +
By this is meant using common debuggers that can operate + using debug data in common formats embedded in the executable. + A specialized debugger useful only with that language is not required. +

+ +

Struct member alignment control +
Although many C/C++ compilers contain pragmas to specify + struct alignment, these are nonstandard and incompatible from + compiler to compiler.
+ The C# standard ECMA-334 25.5.8 says only this about struct member + alignment: + "The order in which members are packed + into a struct is unspecified. For alignment purposes, there may be + unnamed padding at the beginning of a struct, within a struct, and at + the end of the struct. The contents of the bits used as padding are + indeterminate." + Therefore, although Microsoft may + have extensions to support specific member alignment, they are not an + official part of standard C#. +

+ +

Support all C types +
C99 adds many new types not supported by C++. +

+ +

80 bit floating point +
While the standards for C and C++ specify long doubles, few + compilers (besides Digital Mars C/C++) actually implement + 80 bit (or longer) floating point types. +

+ +

Mixins +
Mixins have many different meanings in different programming + languages. D mixins mean taking an arbitrary + sequence of declarations + and inserting (mixing) them into the current scope. Mixins can be done + at the global, class, struct, or local level. +

+ +

C++ Mixins +
C++ mixins refer to a couple different techniques. The first + is analogous to D's interface classes. The second is to create + a template of the form: +
template <class Base> class Mixin : public Base
+{
+    ... mixin body ...
+}
+
+ D mixins are different. +

+ +

Static If +
The C and C++ preprocessor directive #if would appear to + be equivalent to the D static if. But there are major and crucial + differences - the #if does not have access to any of the constants, + types, or symbols of the program. It can only access preprocessor + macros. + See this example. +

+ +

Is Expressions +
Is expressions enable conditional compilation based + on the characteristics of a type. This is done after a fashion in + C++ using template parameter pattern matching. + See this example + for a comparison of the different approaches. +

+ +

Comparison with Ada +
James S. Rogers has written a + comparison chart with Ada. +

+ +

Inner (adaptor) classes +
A nested class is one whose definition is within the scope + of another class. An inner class is a nested class that + can also reference the members and fields of the lexically + enclosing class; one can think of it as if it contained a 'this' + pointer to the enclosing class. +

+ +

Documentation comments +
Documentation comments refer to a standardized way to produce + documentation from the source code file using specialized + comments. + +
+ +

Errors

+ + If I've made any errors in this table, please contact me so + I can correct them: + + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/cppcomplex.html dmd-0.136/dmd/html/d/cppcomplex.html --- dmd-0.135/dmd/html/d/cppcomplex.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/cppcomplex.html 2005-10-04 18:05:28.000000000 +0200 @@ -1,297 +1,290 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - D Complex Types vs C++ std::complex - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- -D vs C/C++/C#/Java

-Rationale for Builtins

-Converting C to D

-Converting C++ to D

-The C Preprocessor vs D

-D strings vs C++ std::string

-D complex vs C++ std::complex

-D Contract Programming vs C++

-
-
- - -

D Complex Types and C++ std::complex

- - How do D's complex numbers compare with C++'s std::complex class? - -

Syntactical Aesthetics

- - In C++, the complex types are: - -
-	complex<float>
-	complex<double>
-	complex<long double>
-	
- - C++ has no distinct imaginary type. D has 3 complex types and 3 - imaginary types: - -
-	cfloat
-	cdouble
-	creal
-	ifloat
-	idouble
-	ireal
-	
- - A C++ complex number can interact with an arithmetic literal, but - since there is no imaginary type, imaginary numbers can only be - created with the constructor syntax: - -
-	complex<long double> a = 5;		// a = 5 + 0i
-	complex<long double> b(0,7);		// b = 0 + 7i
-	c = a + b + complex<long double>(0,7);	// c = 5 + 14i
-	
- - In D, an imaginary numeric literal has the 'i' suffix. - The corresponding code would be the more natural: - -
-	creal a = 5;		// a = 5 + 0i
-	ireal b = 7i;		// b = 7i
-	c = a + b + 7i;		// c = 5 + 14i
-	
- - For more involved expressions involving constants: - -
-	c = (6 + 2i - 1 + 3i) / 3i;
-	
- - In C++, this would be: - -
-	c = (complex<double>(6,2) + complex<double>(-1,3)) / complex<double>(0,3);
-	
- - or if an imaginary class were added to C++ it might be: - -
-	c = (6 + imaginary<double>(2) - 1 + imaginary<double>(3))) / imaginary<double>(3);
-	
- - In other words, an imaginary number nn can be represented with - just nni rather than writing a constructor call - complex<long double>(0,nn). - -

Efficiency

- - The lack of an imaginary type in C++ means that operations on - imaginary numbers wind up with a lot of extra computations done - on the 0 real part. For example, adding two imaginary numbers - in D is one add: - -
-	ireal a, b, c;
-	c = a + b;
-	
- - In C++, it is two adds, as the real parts get added too: - -
-	c.re = a.re + b.re;
-	c.im = a.im + b.im;
-	
- - Multiply is worse, as 4 multiplies and two adds are done instead of - one multiply: - -
-	c.re = a.re * b.re - a.im * b.im;
-	c.im = a.im * b.re + a.re * b.im;
-	
- - Divide is the worst - D has one divide, whereas C++ implements - complex division with typically one comparison, 3 divides, - 3 multiplies and 3 additions: - -
-	if (fabs(b.re) < fabs(b.im))
-	{
-	    r = b.re / b.im;
-	    den = b.im + r * b.re;
-	    c.re = (a.re * r + a.im) / den;
-	    c.im = (a.im * r - a.re) / den;
-	}
-	else
-	{
-	    r = b.im / b.re;
-	    den = b.re + r * b.im;
-	    c.re = (a.re + r * a.im) / den;
-	    c.im = (a.im - r * a.re) / den;
-	}
-	
- - To avoid these efficiency concerns in C++, one could simulate - an imaginary number using a double. For example, given the D: - -
-	cdouble c;
-	idouble im;
-	c *= im;
-	
- - it could be written in C++ as: - -
-	complex<double> c;
-	double im;
-	c = complex<double>(-c.imag() * im, c.real() * im);
-	
- - but then the advantages of complex being a library type integrated - in with the arithmetic operators have been lost. - -

Semantics

- - Worst of all, the lack of an imaginary type can cause the wrong - answer to be inadvertently produced. - To quote - Prof. Kahan: - -
- "A streamline goes astray when the complex functions SQRT and LOG - are implemented, as is necessary in Fortran and in libraries - currently distributed with C/C++ compilers, in a way that - disregards the sign of 0.0 in IEEE 754 arithmetic and consequently - violates identities like SQRT( CONJ( Z ) ) = CONJ( SQRT( Z ) ) and - LOG( CONJ( Z ) ) = CONJ( LOG( Z ) ) whenever the COMPLEX variable Z - takes negative real values. Such anomalies are unavoidable if - Complex Arithmetic operates on pairs (x, y) instead of notional - sums x + i*y of real and imaginary - variables. The language of pairs is incorrect for Complex - Arithmetic; it needs the Imaginary type." -
- - The semantic problems are: - -
    -
  • Consider the formula (1 - infinity*i) * i which - should produce (infinity + i). However, if instead the second - factor is (0 + i) rather than just i, the result is - (infinity + NaN*i), a spurious NaN was generated. - -
  • A distinct imaginary type preserves the sign of 0, necessary - for calculations involving branch cuts. -
- - Appendix G of the C99 standard has recommendations for dealing - with this problem. However, those recommendations are not part - of the C++98 standard, and so cannot be portably relied upon. - -

References

- - - How Java's Floating-Point Hurts Everyone Everywhere - Prof. W. Kahan and Joseph D. Darcy -

- - - The Numerical Analyst as Computer Science Curmudgeon - by Prof. W. Kahan -

- - "Branch Cuts for Complex Elementary Functions, - or Much Ado About Nothing's Sign Bit" - by W. Kahan, ch.
- 7 in The State of the Art in Numerical Analysis (1987) - ed. by M. Powell and A. Iserles for Oxford U.P. - -

-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - D Complex Types vs C++ std::complex + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:28 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· D vs C/C++/C#/Java
+ + +· Rationale for Builtins
+ + +· Converting C to D
+ + +· Converting C++ to D
+ + +· The C Preprocessor vs D
+ + +· D strings vs C++ std::string
+ + +· D complex vs C++ std::complex
+ + +· D Contract Programming vs C++
+ + +
+
+ +

D Complex Types and C++ std::complex

+ + How do D's complex numbers compare with C++'s std::complex class? + +

Syntactical Aesthetics

+ + In C++, the complex types are: + +
complex<float>
+complex<double>
+complex<long double>
+
+ + C++ has no distinct imaginary type. D has 3 complex types and 3 + imaginary types: + +
cfloat
+cdouble
+creal
+ifloat
+idouble
+ireal
+
+ + A C++ complex number can interact with an arithmetic literal, but + since there is no imaginary type, imaginary numbers can only be + created with the constructor syntax: + +
complex<long double> a = 5;		// a = 5 + 0i
+complex<long double> b(0,7);		// b = 0 + 7i
+c = a + b + complex<long double>(0,7);	// c = 5 + 14i
+
+ + In D, an imaginary numeric literal has the 'i' suffix. + The corresponding code would be the more natural: + +
creal a = 5;		// a = 5 + 0i
+ireal b = 7i;		// b = 7i
+c = a + b + 7i;		// c = 5 + 14i
+
+ + For more involved expressions involving constants: + +
c = (6 + 2i - 1 + 3i) / 3i;
+
+ + In C++, this would be: + +
c = (complex<double>(6,2) + complex<double>(-1,3)) / complex<double>(0,3);
+
+ + or if an imaginary class were added to C++ it might be: + +
c = (6 + imaginary<double>(2) - 1 + imaginary<double>(3)) / imaginary<double>(3);
+
+ + In other words, an imaginary number nn can be represented with + just nni rather than writing a constructor call + complex<long double>(0,nn). + +

Efficiency

+ + The lack of an imaginary type in C++ means that operations on + imaginary numbers wind up with a lot of extra computations done + on the 0 real part. For example, adding two imaginary numbers + in D is one add: + +
ireal a, b, c;
+c = a + b;
+
+ + In C++, it is two adds, as the real parts get added too: + +
c.re = a.re + b.re;
+c.im = a.im + b.im;
+
+ + Multiply is worse, as 4 multiplies and two adds are done instead of + one multiply: + +
c.re = a.re * b.re - a.im * b.im;
+c.im = a.im * b.re + a.re * b.im;
+
+ + Divide is the worst - D has one divide, whereas C++ implements + complex division with typically one comparison, 3 divides, + 3 multiplies and 3 additions: + +
if (fabs(b.re) < fabs(b.im))
+{
+    r = b.re / b.im;
+    den = b.im + r * b.re;
+    c.re = (a.re * r + a.im) / den;
+    c.im = (a.im * r - a.re) / den;
+}
+else
+{
+    r = b.im / b.re;
+    den = b.re + r * b.im;
+    c.re = (a.re + r * a.im) / den;
+    c.im = (a.im - r * a.re) / den;
+}
+
+ + To avoid these efficiency concerns in C++, one could simulate + an imaginary number using a double. For example, given the D: + +
cdouble c;
+idouble im;
+c *= im;
+
+ + it could be written in C++ as: + +
complex<double> c;
+double im;
+c = complex<double>(-c.imag() * im, c.real() * im);
+
+ + but then the advantages of complex being a library type integrated + in with the arithmetic operators have been lost. + +

Semantics

+ + Worst of all, the lack of an imaginary type can cause the wrong + answer to be inadvertently produced. + To quote + Prof. Kahan: + +
+ "A streamline goes astray when the complex functions SQRT and LOG + are implemented, as is necessary in Fortran and in libraries + currently distributed with C/C++ compilers, in a way that + disregards the sign of 0.0 in IEEE 754 arithmetic and consequently + violates identities like SQRT( CONJ( Z ) ) = CONJ( SQRT( Z ) ) and + LOG( CONJ( Z ) ) = CONJ( LOG( Z ) ) whenever the COMPLEX variable Z + takes negative real values. Such anomalies are unavoidable if + Complex Arithmetic operates on pairs (x, y) instead of notional + sums x + i*y of real and imaginary + variables. The language of pairs is incorrect for Complex + Arithmetic; it needs the Imaginary type." +
+ + The semantic problems are: + +
    +
  • Consider the formula (1 - infinity*i) * i which + should produce (infinity + i). However, if instead the second + factor is (0 + i) rather than just i, the result is + (infinity + NaN*i), a spurious NaN was generated. + +
  • A distinct imaginary type preserves the sign of 0, necessary + for calculations involving branch cuts. +
+ + Appendix G of the C99 standard has recommendations for dealing + with this problem. However, those recommendations are not part + of the C++98 standard, and so cannot be portably relied upon. + +

References

+ + + How Java's Floating-Point Hurts Everyone Everywhere + Prof. W. Kahan and Joseph D. Darcy +

+ + + The Numerical Analyst as Computer Science Curmudgeon + by Prof. W. Kahan +

+ + "Branch Cuts for Complex Elementary Functions, + or Much Ado About Nothing's Sign Bit" + by W. Kahan, ch.
+ 7 in The State of the Art in Numerical Analysis (1987) + ed. by M. Powell and A. Iserles for Oxford U.P. + + +

+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/cppdbc.html dmd-0.136/dmd/html/d/cppdbc.html --- dmd-0.135/dmd/html/d/cppdbc.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/cppdbc.html 2005-10-17 00:39:32.000000000 +0200 @@ -1,591 +1,583 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - D's Contract Programming vs C++'s - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- -D vs C/C++/C#/Java

-Rationale for Builtins

-Converting C to D

-Converting C++ to D

-The C Preprocessor vs D

-D strings vs C++ std::string

-D complex vs C++ std::complex

-D Contract Programming vs C++

-
-
- - -

D's Contract Programming vs C++'s

- - Many people have written me saying that D's Contract Programming - (DbC) does not add anything that C++ does not already support. - They go on to illustrate their point with a technique for doing DbC in - C++. -

- - It makes sense to review what DbC is, how it is done in D, - and stack that up with what each of the various C++ DbC techniques - can do. -

- - Digital Mars C++ adds - extensions to C++ - to support DbC, but they are not covered here because they are not - part of standard C++ and are not supported by any other C++ compiler. - -

Contract Programming in D

- - This is more fully documented in the D - Contract Programming document. - To sum up, DbC in D has the following characteristics: - -
    - -
  1. The assert is the basic contract. - -
  2. When an assert contract fails, it throws an exception. - Such exceptions can be caught and handled, or allowed to - terminate the program. - -
  3. Classes can have class invariants which are - checked upon entry and exit of each public class member function, - the exit of each constructor, and the entry of the destructor. - -
  4. Assert contracts on object references check the class - invariant for that object. - -
  5. Class invariants are inherited, that means that a derived - class invariant will implicitly call the base class invariant. - -
  6. Functions can have preconditions and postconditions. - -
  7. For member functions in a class inheritance hierarchy, the - precondition of a derived class function are OR'd together - with the preconditions of all the functions it overrides. - The postconditions are AND'd together. - -
  8. By throwing a compiler switch, DbC code can be enabled - or can be withdrawn from the compiled code. - -
  9. Code works semantically the same with or without DbC - checking enabled. - -
- -

Contract Programming in C++

- -

The assert Macro

- - C++ does have the basic assert macro, which tests its argument - and if it fails, aborts the program. assert can be turned - on and off with the NDEBUG macro. -

- - assert does not know anything about class invariants, - and does not throw an exception when it fails. It just aborts - the program after writing a message. assert relies on - a macro text preprocessor to work. -

- - assert is where explicit support for DbC in Standard C++ - begins and ends. - -

Class Invariants

- - Consider a class invariant in D: - -
-	class A
-	{
-	    invariant() { ...contracts... }
-
-	    this() { ... }	// constructor
-	    ~this() { ... }	// destructor
-
-	    void foo() { ... }	// public member function
-	}
-
-	class B : A
-	{
-	    invariant() { ...contracts... }
-	    ...
-	}
-	
- - To accomplish the equivalent in C++ (thanks to Bob Bell for providing - this): - -
-	template
-	inline void check_invariant(T& iX)
-	{
-	#ifdef DBC
-	    iX.invariant();
-	#endif
-	}
-
-	// A.h:
-
-	class A {
-	    public:
-	#ifdef DBG
-	       virtual void invariant() { ...contracts... }
-	#endif
-	       void foo();
-	};
-
-	// A.cpp:
-
-	void A::foo()
-	{
-	    check_invariant(*this);
-	    ...
-	    check_invariant(*this);
-	}
-
-	// B.h:
-
-	#include "A.h"
-
-	class B : public A {
-	    public:
-	#ifdef DBG
-		virtual void invariant()
-		{ ...contracts...
-		   A::invariant();
-		}
-	#endif
-	       void bar();
-	};
-
-	// B.cpp:
-
-	void B::barG()
-	{
-	    check_invariant(*this);
-	    ...
-	    check_invariant(*this);
-	}
-	
- - There's an additional complication with A::foo(). Upon every - normal exit from the function, the invariant() should be - called. - This means that code that looks like: - -
-	int A::foo()
-	{
-	    ...
-	    if (...)
-		return bar();
-	    return 3;
-	}
-	
- - would need to be written as: - -
-	int A::foo()
-	{
-	    int result;
-	    check_invariant(*this);
-	    ...
-	    if (...)
-	    {
-		result = bar();
-		check_invariant(*this);
-		return result;
-	    }
-	    check_invariant(*this);
-	    return 3;
-	}
-	
- - Or recode the function so it has a single exit point. - One possibility to mitigate this is to use RAII techniques: - -
-	int A::foo()
-	{
-	#if DBC
-	    struct Sentry {
-	       Sentry(A& iA) : mA(iA) { check_invariants(iA); }
-	       ~Sentry() { check_invariants(mA); }
-	       A& mA;
-	    } sentry(*this);
-	#endif
-	    ...
-	    if (...)
-		return bar();
-	    return 3;
-	}
-	
- - The #if DBC is still there because some compilers may not - optimize the whole thing away if check_invariants compiles to nothing. - -

Preconditions and Postconditions

- - Consider the following in D: - -
-	void foo()
-	    in { ...preconditions... }
-	    out { ...postconditions... }
-	    body
-	    {
-		...implementation...
-	    }
-	
- - This is nicely handled in C++ with the nested Sentry struct: - -
-	void foo()
-	{
-	    struct Sentry
-	    {	Sentry() { ...preconditions... }
-		~Sentry() { ...postconditions... }
-	    } sentry;
-	    ...implementation...
-	}
-	
- - If the preconditions and postconditions consist of nothing - more than assert macros, the whole doesn't need to - be wrapped in a #ifdef pair, since a good C++ compiler will - optimize the whole thing away if the asserts are turned off. -

- - But suppose foo() sorts an array, and the postcondition needs - to walk the array and verify that it really is sorted. Now - the shebang needs to be wrapped in #ifdef: - -

-	void foo()
-	{
-	#ifdef DBC
-	    struct Sentry
-	    {	Sentry() { ...preconditions... }
-		~Sentry() { ...postconditions... }
-	    } sentry;
-	#endif
-	    ...implementation...
-	}
-	
- - (One can make use of the C++ rule that templates are only - instantiated when used can be used to avoid the #ifdef, by - putting the conditions into a template function referenced - by the assert.) -

- - Let's add a return value to foo() that needs to be checked in - the postconditions. In D: - -

-	int foo()
-	    in { ...preconditions... }
-	    out (result) { ...postconditions... }
-	    body
-	    {
-		...implementation...
-		if (...)
-		    return bar();
-		return 3;
-	    }
-	
- - In C++: - -
-	int foo()
-	{
-	#ifdef DBC
-	    struct Sentry
-	    {	int result;
-		Sentry() { ...preconditions... }
-		~Sentry() { ...postconditions... }
-	    } sentry;
-	#endif
-	    ...implementation...
-	    if (...)
-	    {   int i = bar();
-	#ifdef DBC
-		sentry.result = i;
-	#endif
-		return i;
-	    }
-	#ifdef DBC
-	    sentry.result = 3;
-	#endif
-	    return 3;
-	}
-	
- - Now add a couple parameters to foo(). In D: - -
-	int foo(int a, int b)
-	    in { ...preconditions... }
-	    out (result) { ...postconditions... }
-	    body
-	    {
-		...implementation...
-		if (...)
-		    return bar();
-		return 3;
-	    }
-	
- - In C++: - -
-	int foo(int a, int b)
-	{
-	#ifdef DBC
-	    struct Sentry
-	    {	int a, b;
-		int result;
-		Sentry(int a, int b)
-		{   this->a = a;
-		    this->b = b;
-		    ...preconditions...
-		}
-		~Sentry() { ...postconditions... }
-	    } sentry(a,b);
-	#endif
-	    ...implementation...
-		if (...)
-		{   int i = bar();
-	#ifdef DBC
-		    sentry.result = i;
-	#endif
-		    return i;
-		}
-	#ifdef DBC
-		sentry.result = 3;
-	#endif
-		return 3;
-	}
-	
- -

Preconditions and Postconditions for Member Functions

- - Consider the use of preconditions and postconditions for a - polymorphic function in D: - -
-	class A
-	{
-	    void foo()
-		in { ...Apreconditions... }
-		out { ...Apostconditions... }
-		body
-		{
-		    ...implementation...
-		}
-	}
-
-	class B : A
-	{
-	    void foo()
-		in { ...Bpreconditions... }
-		out { ...Bpostconditions... }
-		body
-		{
-		    ...implementation...
-		}
-	}
-	
- - The semantics for a call to B.foo() are: - -
    -
  • Either Apreconditions or Bpreconditions must be satisfied. -
  • Both Apostconditions and Bpostconditions must be satisfied. -
- - Let's get this to work in C++: - -
-	class A
-	{
-	protected:
-	    #if DBC
-	    int foo_preconditions() { ...Apreconditions... }
-	    void foo_postconditions() { ...Apostconditions... }
-	    #else
-	    int foo_preconditions() { return 1; }
-	    void foo_postconditions() { }
-	    #endif
-
-	    void foo_internal()
-	    {
-		...implementation...
-	    }
-
-	public:
-	    virtual void foo()
-	    {
-		foo_preconditions();
-		foo_internal();
-		foo_postconditions();
-	    }
-	};
-
-	class B : A
-	{
-	protected:
-	    #if DBC
-	    int foo_preconditions() { ...Bpreconditions... }
-	    void foo_postconditions() { ...Bpostconditions... }
-	    #else
-	    int foo_preconditions() { return 1; }
-	    void foo_postconditions() { }
-	    #endif
-
-	    void foo_internal()
-	    {
-		...implementation...
-	    }
-
-	public:
-	    virtual void foo()
-	    {
-		assert(foo_preconditions() || A::foo_preconditions());
-		foo_internal();
-		A::foo_postconditions();
-		foo_postconditions();
-	    }
-	};
-	
- - Something interesting has happened here. The preconditions can - no longer be done using assert, since the results need - to be OR'd together. I'll leave as a reader exercise adding - in a class invariant, function return values for foo(), - and parameters - for foo(). - -

Conclusion

- - These C++ techniques can work up to a point. But, aside from - assert, they are not standardized and so will vary from - project to project. Furthermore, they require much tedious - adhesion to a particular convention, and add significant clutter - to the code. Perhaps that's why it's rarely seen in practice. -

- - By adding support for DbC into the language, D offers an easy - way to use DbC and get it right. Being in the language standardizes - the way it will be used from project to project. - -

References

- - Chapter C.11 introduces the theory and rationale of - Contract Programming in - - Object-Oriented Software Construction -
- Bertrand Meyer, Prentice Hall -

- - Chapters 24.3.7.1 to 24.3.7.3 discuss Contract Programming in C++ in - - The C++ Programming Language Special Edition -
- Bjarne Stroustrup, Addison-Wesley -

- -

-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - D's Contract Programming vs C++'s + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Mon Oct 17 00:39:30 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· D vs C/C++/C#/Java
+ + +· Rationale for Builtins
+ + +· Converting C to D
+ + +· Converting C++ to D
+ + +· The C Preprocessor vs D
+ + +· D strings vs C++ std::string
+ + +· D complex vs C++ std::complex
+ + +· D Contract Programming vs C++
+ + +
+
+ +

D's Contract Programming vs C++'s

+ + Many people have written me saying that D's Contract Programming + (DbC) does not add anything that C++ does not already support. + They go on to illustrate their point with a technique for doing DbC in + C++. +

+ + It makes sense to review what DbC is, how it is done in D, + and stack that up with what each of the various C++ DbC techniques + can do. +

+ + Digital Mars C++ adds + extensions to C++ + to support DbC, but they are not covered here because they are not + part of standard C++ and are not supported by any other C++ compiler. + +

Contract Programming in D

+ + This is more fully documented in the D + Contract Programming document. + To sum up, DbC in D has the following characteristics: + +
    + +
  1. The assert is the basic contract. + +
  2. When an assert contract fails, it throws an exception. + Such exceptions can be caught and handled, or allowed to + terminate the program. + +
  3. Classes can have class invariants which are + checked upon entry and exit of each public class member function, + the exit of each constructor, and the entry of the destructor. + +
  4. Assert contracts on object references check the class + invariant for that object. + +
  5. Class invariants are inherited, that means that a derived + class invariant will implicitly call the base class invariant. + +
  6. Functions can have preconditions and postconditions. + +
  7. For member functions in a class inheritance hierarchy, the + precondition of a derived class function are OR'd together + with the preconditions of all the functions it overrides. + The postconditions are AND'd together. + +
  8. By throwing a compiler switch, DbC code can be enabled + or can be withdrawn from the compiled code. + +
  9. Code works semantically the same with or without DbC + checking enabled. + +
+ +

Contract Programming in C++

+ +

The assert Macro

+ + C++ does have the basic assert macro, which tests its argument + and if it fails, aborts the program. assert can be turned + on and off with the NDEBUG macro. +

+ + assert does not know anything about class invariants, + and does not throw an exception when it fails. It just aborts + the program after writing a message. assert relies on + a macro text preprocessor to work. +

+ + assert is where explicit support for DbC in Standard C++ + begins and ends. + +

Class Invariants

+ + Consider a class invariant in D: + +
class A
+{
+    invariant() { ...contracts... }
+
+    this() { ... }	// constructor
+    ~this() { ... }	// destructor
+
+    void foo() { ... }	// public member function
+}
+
+class B : A
+{
+    invariant() { ...contracts... }
+    ...
+}
+
+ + To accomplish the equivalent in C++ (thanks to Bob Bell for providing + this): + +
template
+inline void check_invariant(T& iX)
+{
+#ifdef DBC
+    iX.invariant();
+#endif
+}
+
+// A.h:
+
+class A {
+    public:
+#ifdef DBG
+       virtual void invariant() { ...contracts... }
+#endif
+       void foo();
+};
+
+// A.cpp:
+
+void A::foo()
+{
+    check_invariant(*this);
+    ...
+    check_invariant(*this);
+}
+
+// B.h:
+
+#include "A.h"
+
+class B : public A {
+    public:
+#ifdef DBG
+	virtual void invariant()
+	{   ...contracts...
+	   A::invariant();
+	}
+#endif
+       void bar();
+};
+
+// B.cpp:
+
+void B::barG()
+{
+    check_invariant(*this);
+    ...
+    check_invariant(*this);
+}
+
+ + There's an additional complication with A::foo(). Upon every + normal exit from the function, the invariant() should be + called. + This means that code that looks like: + +
int A::foo()
+{
+    ...
+    if (...)
+	return bar();
+    return 3;
+}
+
+ + would need to be written as: + +
int A::foo()
+{
+    int result;
+    check_invariant(*this);
+    ...
+    if (...)
+    {
+	result = bar();
+	check_invariant(*this);
+	return result;
+    }
+    check_invariant(*this);
+    return 3;
+}
+
+ + Or recode the function so it has a single exit point. + One possibility to mitigate this is to use RAII techniques: + +
int A::foo()
+{
+#if DBC
+    struct Sentry {
+       Sentry(A& iA) : mA(iA) { check_invariants(iA); }
+       ~Sentry() { check_invariants(mA); }
+       A& mA;
+    } sentry(*this);
+#endif
+    ...
+    if (...)
+	return bar();
+    return 3;
+}
+
+ + The #if DBC is still there because some compilers may not + optimize the whole thing away if check_invariants compiles to nothing. + +

Preconditions and Postconditions

+ + Consider the following in D: + +
void foo()
+    in { ...preconditions... }
+    out { ...postconditions... }
+    body
+    {
+	...implementation...
+    }
+
+ + This is nicely handled in C++ with the nested Sentry struct: + +
void foo()
+{
+    struct Sentry
+    {   Sentry() { ...preconditions... }
+	~Sentry() { ...postconditions... }
+    } sentry;
+    ...implementation...
+}
+
+ + If the preconditions and postconditions consist of nothing + more than assert macros, the whole doesn't need to + be wrapped in a #ifdef pair, since a good C++ compiler will + optimize the whole thing away if the asserts are turned off. +

+ + But suppose foo() sorts an array, and the postcondition needs + to walk the array and verify that it really is sorted. Now + the shebang needs to be wrapped in #ifdef: + +

void foo()
+{
+#ifdef DBC
+    struct Sentry
+    {   Sentry() { ...preconditions... }
+	~Sentry() { ...postconditions... }
+    } sentry;
+#endif
+    ...implementation...
+}
+
+ + (One can make use of the C++ rule that templates are only + instantiated when used can be used to avoid the #ifdef, by + putting the conditions into a template function referenced + by the assert.) +

+ + Let's add a return value to foo() that needs to be checked in + the postconditions. In D: + +

int foo()
+    in { ...preconditions... }
+    out (result) { ...postconditions... }
+    body
+    {
+	...implementation...
+	if (...)
+	    return bar();
+	return 3;
+    }
+
+ + In C++: + +
int foo()
+{
+#ifdef DBC
+    struct Sentry
+    {   int result;
+	Sentry() { ...preconditions... }
+	~Sentry() { ...postconditions... }
+    } sentry;
+#endif
+    ...implementation...
+    if (...)
+    {   int i = bar();
+#ifdef DBC
+	sentry.result = i;
+#endif
+	return i;
+    }
+#ifdef DBC
+    sentry.result = 3;
+#endif
+    return 3;
+}
+
+ + Now add a couple parameters to foo(). In D: + +
int foo(int a, int b)
+    in { ...preconditions... }
+    out (result) { ...postconditions... }
+    body
+    {
+	...implementation...
+	if (...)
+	    return bar();
+	return 3;
+    }
+
+ + In C++: + +
int foo(int a, int b)
+{
+#ifdef DBC
+    struct Sentry
+    {   int a, b;
+	int result;
+	Sentry(int a, int b)
+	{   this->a = a;
+	    this->b = b;
+	    ...preconditions...
+	}
+	~Sentry() { ...postconditions... }
+    } sentry(a,b);
+#endif
+    ...implementation...
+	if (...)
+	{   int i = bar();
+#ifdef DBC
+	    sentry.result = i;
+#endif
+	    return i;
+	}
+#ifdef DBC
+	sentry.result = 3;
+#endif
+	return 3;
+}
+
+ +

Preconditions and Postconditions for Member Functions

+ + Consider the use of preconditions and postconditions for a + polymorphic function in D: + +
class A
+{
+    void foo()
+	in { ...Apreconditions... }
+	out { ...Apostconditions... }
+	body
+	{
+	    ...implementation...
+	}
+}
+
+class B : A
+{
+    void foo()
+	in { ...Bpreconditions... }
+	out { ...Bpostconditions... }
+	body
+	{
+	    ...implementation...
+	}
+}
+
+ + The semantics for a call to B.foo() are: + +
    +
  • Either Apreconditions or Bpreconditions must be satisfied. +
  • Both Apostconditions and Bpostconditions must be satisfied. +
+ + Let's get this to work in C++: + +
class A
+{
+protected:
+    #if DBC
+    int foo_preconditions() { ...Apreconditions... }
+    void foo_postconditions() { ...Apostconditions... }
+    #else
+    int foo_preconditions() { return 1; }
+    void foo_postconditions() { }
+    #endif
+
+    void foo_internal()
+    {
+	...implementation...
+    }
+
+public:
+    virtual void foo()
+    {
+	foo_preconditions();
+	foo_internal();
+	foo_postconditions();
+    }
+};
+
+class B : A
+{
+protected:
+    #if DBC
+    int foo_preconditions() { ...Bpreconditions... }
+    void foo_postconditions() { ...Bpostconditions... }
+    #else
+    int foo_preconditions() { return 1; }
+    void foo_postconditions() { }
+    #endif
+
+    void foo_internal()
+    {
+	...implementation...
+    }
+
+public:
+    virtual void foo()
+    {
+	assert(foo_preconditions() || A::foo_preconditions());
+	foo_internal();
+	A::foo_postconditions();
+	foo_postconditions();
+    }
+};
+
+ + Something interesting has happened here. The preconditions can + no longer be done using assert, since the results need + to be OR'd together. I'll leave as a reader exercise adding + in a class invariant, function return values for foo(), + and parameters + for foo(). + +

Conclusion

+ + These C++ techniques can work up to a point. But, aside from + assert, they are not standardized and so will vary from + project to project. Furthermore, they require much tedious + adhesion to a particular convention, and add significant clutter + to the code. Perhaps that's why it's rarely seen in practice. +

+ + By adding support for DbC into the language, D offers an easy + way to use DbC and get it right. Being in the language standardizes + the way it will be used from project to project. + +

References

+ + Chapter C.11 introduces the theory and rationale of + Contract Programming in + + Object-Oriented Software Construction +
+ Bertrand Meyer, Prentice Hall +

+ + Chapters 24.3.7.1 to 24.3.7.3 discuss Contract Programming in C++ in + + The C++ Programming Language Special Edition +
+ Bjarne Stroustrup, Addison-Wesley +

+ + +

+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/cppstrings.html dmd-0.136/dmd/html/d/cppstrings.html --- dmd-0.135/dmd/html/d/cppstrings.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/cppstrings.html 2005-10-04 18:05:28.000000000 +0200 @@ -1,611 +1,594 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - D Strings vs C++ Strings - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- -D vs C/C++/C#/Java

-Rationale for Builtins

-Converting C to D

-Converting C++ to D

-The C Preprocessor vs D

-D strings vs C++ std::string

-D complex vs C++ std::complex

-D Contract Programming vs C++

-
-
- - -

D Strings vs C++ Strings

- - -Why have strings built-in to the core language of D rather than entirely in -a library as in C++ Strings? What's the point? Where's the improvement? - -

Concatenation Operator

- - C++ Strings are stuck with overloading existing operators. The - obvious choice for concatenation is += and +. - But someone just looking at the code will see + and think "addition". - He'll have to look up the types (and types are frequently buried - behind multiple typedef's) to see that it's a string type, and - it's not adding strings but concatenating them. -

- - Additionally, if one has an array of floats, is '+' overloaded to - be the same as a vector addition, or an array concatenation? -

- - In D, these problems are avoided by introducing a new binary - operator ~ as the concatenation operator. It works with - arrays (of which strings are a subset). ~= is the corresponding - append operator. ~ on arrays of floats would concatenate them, - + would imply a vector add. Adding a new operator makes it possible - for orthogonality and consistency in the treatment of arrays. - (In D, strings are simply arrays of characters, not a special - type.) - -

Interoperability With C String Syntax

- - Overloading of operators only really works if one of the operands - is overloadable. So the C++ string class cannot consistently - handle arbitrary expressions containing strings. Consider: - -
-        const char abc[5] = "world";
-        string str = "hello" + abc;
-
-
- - That isn't going to work. But it does work when the core language - knows about strings: - -
-	const char[5] abc = "world";
-	char[] str = "hello" ~ abc;
-
-
- -

Consistency With C String Syntax

- - There are three ways to find the length of a string in C++: - -
-	const char abc[] = "world";	:	sizeof(abc)/sizeof(abc[0])-1
-					:	strlen(abc)
-	string str			:	str.length()
-
-
- - That kind of inconsistency makes it hard to write generic templates. - Consider D: - -
-	char[5] abc = "world";	:	abc.length
-	char[] str		:	str.length
-
-
- -

Checking For Empty Strings

- - C++ strings use a function to determine if a string is empty: -
-	string str;
-	if (str.empty())
-		// string is empty
-
- - In D, an empty string has zero length: - -
-	char[] str;
-	if (!str.length)
-		// string is empty
-
- - -

Resizing Existing String

- - C++ handles this with the resize() member function: - -
-	string str;
-	str.resize(newsize);
-
- - D takes advantage of knowing that str is a string, and - so resizing it is just changing the length property: - -
-	char[] str;
-	str.length = newsize;
-
- -

Slicing a String

- - C++ slices an existing string using a special constructor: - -
-	string s1 = "hello world";
-	string s2(s1, 6, 5);		// s2 is "world"
-
- - D has the array slice syntax, not possible with C++: - -
-	char[] s1 = "hello world";
-	char[] s2 = s1[6 .. 11];	// s2 is "world"
-
- - Slicing, of course, works with any array in D, not just strings. - -

Copying a String

- - C++ copies strings with the replace function: - -
-	string s1 = "hello world";
-	string s2 = "goodbye      ";
-	s2.replace(8, 5, s1, 6, 5);	// s2 is "goodbye world"
-
- - D uses the slice syntax as an lvalue: - -
-	char[] s1 = "hello world";
-	char[] s2 = "goodbye      ";
-	s2[8..13] = s1[6..11];		// s2 is "goodbye world"
-
- -

Conversions to C Strings

- - This is needed for compatibility with C API's. In C++, this - uses the c_str() member function: - -
-	void foo(const char *);
-	string s1;
-	foo(s1.c_str());
-
- - In D, strings can be implicitly converted to char*: - -
-	void foo(char *);
-	char[] s1;
-	foo(s1);
-
- - Note: some will argue that it is a mistake in D to have an implicit - conversion from char[] to char*. - -

Array Bounds Checking

- - In C++, string array bounds checking for [] is not done. - In D, array bounds checking is on by default and it can be turned off - with a compiler switch after the program is debugged. - -

String Switch Statements

- - Are not possible in C++, nor is there any way to add them - by adding more to the library. In D, they take the obvious - syntactical forms: - -
-	switch (str)
-	{
-	    case "hello":
-	    case "world":
-		...
-	}
-
- - where str can be any of literal "string"s, fixed string arrays - like char[10], or dynamic strings like char[]. A quality implementation - can, of course, explore many strategies of efficiently implementing - this based on the contents of the case strings. - -

Filling a String

- - In C++, this is done with the replace() member function: - -
-	string str = "hello";
-	str.replace(1,2,2,'?');		// str is "h??lo"
-
- - In D, use the array slicing syntax in the natural manner: - -
-	char[] str = "hello";
-	str[1..2] = '?';		// str is "h??lo"
-
- -

Value vs Reference

- - C++ strings, as implemented by STLport, are by value and are - 0-terminated. [The latter is an implementation choice, but - STLport seems to be the most popular implementation.] - This, coupled with no garbage collection, has - some consequences. First of all, any string created must make - its own copy of the string data. The 'owner' of the string - data must be kept track of, because when the owner is deleted - all references become invalid. If one tries to avoid the - dangling reference problem by treating strings as value types, - there will be a lot of overhead of memory allocation, - data copying, and memory deallocation. Next, the 0-termination - implies that strings cannot refer to other strings. String - data in the data segment, stack, etc., cannot - be referred to. -

- - D strings are reference types, and the memory is garbage collected. - This means that only references need to be copied, not the - string data. D strings can refer to data in the static data - segment, data on the stack, data inside other strings, objects, - file buffers, etc. There's no need to keep track of the 'owner' - of the string data. -

- - The obvious question is if multiple D strings refer to the same - string data, what happens if the data is modified? All the - references will now point to the modified data. This can have - its own consequences, which can be avoided if the copy-on-write - convention is followed. All copy-on-write is is that if - a string is written to, an actual copy of the string data is made - first. -

- - The result of D strings being reference only and garbage collected - is that code that does a lot of string manipulating, such as - an lzw compressor, can be a lot more efficient in terms of both - memory consumption and speed. - -

Benchmark

- - Let's take a look at a small utility, wordcount, that counts up - the frequency of each word in a text file. In D, it looks like this: - -
-	import file;
-
-	int main (char[][] args)
-	{
-	    int w_total;
-	    int l_total;
-	    int c_total;
-	    int[char[]] dictionary;
-
-	    printf("   lines   words   bytes file\n");
-	    for (int i = 1; i < args.length; ++i)
-	    {
-		char[] input;
-		int w_cnt, l_cnt, c_cnt;
-		int inword;
-		int wstart;
-
-		input = cast(char[])file.read(args[i]);
-
-		for (int j = 0; j < input.length; j++)
-		{   char c;
-
-		    c = input[j];
-		    if (c == '\n')
-			++l_cnt;
-		    if (c >= '0' && c <= '9')
-		    {
-		    }
-		    else if (c >= 'a' && c <= 'z' ||
-			c >= 'A' && c <= 'Z')
-		    {
-			if (!inword)
-			{
-			    wstart = j;
-			    inword = 1;
-			    ++w_cnt;
-			}
-		    }
-		    else if (inword)
-		    {   char[] word = input[wstart .. j];
-
-			dictionary[word]++;
-			inword = 0;
-		    }
-		    ++c_cnt;
-		}
-		if (inword)
-		{   char[] w = input[wstart .. input.length];
-		    dictionary[w]++;
-		}
-		printf("%8lu%8lu%8lu %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
-		l_total += l_cnt;
-		w_total += w_cnt;
-		c_total += c_cnt;
-	    }
-
-	    if (args.length > 2)
-	    {
-		printf("--------------------------------------\n%8lu%8lu%8lu total",
-		    l_total, w_total, c_total);
-	    }
-
-	    printf("--------------------------------------\n");
-
-	    foreach (char[] word1; dictionary.keys.sort)
-	    {
-		printf("%3d %.*s\n", dictionary[word1], word1);
-	    }
-	    return 0;
-	}
-	
- - Two people have written C++ implementations using the C++ standard - template library, - wccpp1 - and - wccpp2. - The input file - alice30.txt - is the text of "Alice in Wonderland." - The D compiler, - dmd, - and the C++ compiler, - dmc, - share the same - optimizer and code generator, which provides a more apples to - apples comparison of the efficiency of the semantics of the languages - rather than the optimization and code generator sophistication. - Tests were run on a Win XP machine. dmc uses STLport for the template - implementation. -

- - - - - - -
Program - Compile - Compile Time - Run - Run Time -
D wc - dmd wc -O -release - 0.0719 - wc alice30.txt >log - 0.0326 -
C++ wccpp1 - dmc wccpp1 -o -I\dm\stlport\stlport - 2.1917 - wccpp1 alice30.txt >log - 0.0944 -
C++ wccpp2 - dmc wccpp2 -o -I\dm\stlport\stlport - 2.0463 - wccpp2 alice30.txt >log - 0.1012 -
-

- - The following tests were run on linux, again comparing a D compiler - (gdc) - and a C++ compiler (g++) that share a common optimizer and - code generator. The system is Pentium III 800MHz running RedHat Linux 8.0 - and gcc 3.4.2. - The Digital Mars D compiler for linux (dmd) - is included for comparison. -

- - - - - - - - -
Program - Compile - Compile Time - Run - Run Time -
D wc - gdc -O2 -frelease -o wc wc.d - 0.326 - wc alice30.txt > /dev/null - 0.041 -
D wc - dmd wc -O -release - 0.235 - wc alice30.txt > /dev/null - 0.041 -
C++ wccpp1 - g++ -O2 -o wccpp1 wccpp1.cc - 2.874 - wccpp1 alice30.txt > /dev/null - 0.086 -
C++ wccpp2 - g++ -O2 -o wccpp2 wccpp2.cc - 2.886 - wccpp2 alice30.txt > /dev/null - 0.095 -
-

- - These tests compare gdc with g++ on a PowerMac G5 2x2.0GHz - running MacOS X 10.3.5 and gcc 3.4.2. (Timings are a little - less accurate.) -

- - - - - - -
Program - Compile - Compile Time - Run - Run Time -
D wc - gdc -O2 -frelease -o wc wc.d - 0.28 - wc alice30.txt > /dev/null - 0.03 -
C++ wccpp1 - g++ -O2 -o wccpp1 wccpp1.cc - 1.90 - wccpp1 alice30.txt > /dev/null - 0.07 -
C++ wccpp2 - g++ -O2 -o wccpp2 wccpp2.cc - 1.88 - wccpp2 alice30.txt > /dev/null - 0.08 -
-


-

wccpp2 by Allan Odgaard

- -
-	#include <algorithm>
-	#include <cstdio>
-	#include <fstream>
-	#include <iterator>
-	#include <map>
-	#include <vector>
-
-	bool isWordStartChar (char c)	{ return isalpha(c); }
-	bool isWordEndChar (char c)	{ return !isalnum(c); }
-
-	int main (int argc, char const* argv[])
-	{
-	    using namespace std;
-	    printf("Lines Words Bytes File:\n");
-
-	    map<string, int> dict;
-	    int tLines = 0, tWords = 0, tBytes = 0;
-	    for(int i = 1; i < argc; i++)
-	    {
-		ifstream file(argv[i]);
-		istreambuf_iterator<char> from(file.rdbuf()), to;
-		vector<char> v(from, to);
-		vector<char>::iterator first = v.begin(), last = v.end(), bow, eow;
-
-		int numLines = count(first, last, '\n');
-		int numWords = 0;
-		int numBytes = last - first;
-
-		for(eow = first; eow != last; )
-		{
-		    bow = find_if(eow, last, isWordStartChar);
-		    eow = find_if(bow, last, isWordEndChar);
-		    if(bow != eow)
-			++dict[string(bow, eow)], ++numWords;
-		}
-
-		printf("%5d %5d %5d %s\n", numLines, numWords, numBytes, argv[i]);
-
-		tLines += numLines;
-		tWords += numWords;
-		tBytes += numBytes;
-	    }
-
-	    if(argc > 2)
-		    printf("-----------------------\n%5d %5d %5d\n", tLines, tWords, tBytes);
-	    printf("-----------------------\n\n");
-
-	    for(map<string, int>::const_iterator it = dict.begin(); it != dict.end(); ++it)
-		    printf("%5d %s\n", it->second, it->first.c_str());
-
-	    return 0;
-	}
-	
- -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - D Strings vs C++ Strings + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:28 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· D vs C/C++/C#/Java
+ + +· Rationale for Builtins
+ + +· Converting C to D
+ + +· Converting C++ to D
+ + +· The C Preprocessor vs D
+ + +· D strings vs C++ std::string
+ + +· D complex vs C++ std::complex
+ + +· D Contract Programming vs C++
+ + +
+
+ +

D Strings vs C++ Strings

+ + +Why have strings built-in to the core language of D rather than entirely in +a library as in C++ Strings? What's the point? Where's the improvement? + +

Concatenation Operator

+ + C++ Strings are stuck with overloading existing operators. The + obvious choice for concatenation is += and +. + But someone just looking at the code will see + and think "addition". + He'll have to look up the types (and types are frequently buried + behind multiple typedef's) to see that it's a string type, and + it's not adding strings but concatenating them. +

+ + Additionally, if one has an array of floats, is '+' overloaded to + be the same as a vector addition, or an array concatenation? +

+ + In D, these problems are avoided by introducing a new binary + operator ~ as the concatenation operator. It works with + arrays (of which strings are a subset). ~= is the corresponding + append operator. ~ on arrays of floats would concatenate them, + + would imply a vector add. Adding a new operator makes it possible + for orthogonality and consistency in the treatment of arrays. + (In D, strings are simply arrays of characters, not a special + type.) + +

Interoperability With C String Syntax

+ + Overloading of operators only really works if one of the operands + is overloadable. So the C++ string class cannot consistently + handle arbitrary expressions containing strings. Consider: + +
        const char abc[5] = "world";
+        string str = "hello" + abc;
+
+ + That isn't going to work. But it does work when the core language + knows about strings: + +
	const char[5] abc = "world";
+	char[] str = "hello" ~ abc;
+
+ +

Consistency With C String Syntax

+ + There are three ways to find the length of a string in C++: + +
	const char abc[] = "world";	:	sizeof(abc)/sizeof(abc[0])-1
+					:	strlen(abc)
+	string str			:	str.length()
+
+ + That kind of inconsistency makes it hard to write generic templates. + Consider D: + +
	char[5] abc = "world";	:	abc.length
+	char[] str		:	str.length
+
+ +

Checking For Empty Strings

+ + C++ strings use a function to determine if a string is empty: + +
	string str;
+	if (str.empty())
+		// string is empty
+
+ + In D, an empty string has zero length: + +
	char[] str;
+	if (!str.length)
+		// string is empty
+
+ + +

Resizing Existing String

+ + C++ handles this with the resize() member function: + +
	string str;
+	str.resize(newsize);
+
+ + D takes advantage of knowing that str is a string, and + so resizing it is just changing the length property: + +
	char[] str;
+	str.length = newsize;
+
+ +

Slicing a String

+ + C++ slices an existing string using a special constructor: + +
	string s1 = "hello world";
+	string s2(s1, 6, 5);		// s2 is "world"
+
+ + D has the array slice syntax, not possible with C++: + +
	char[] s1 = "hello world";
+	char[] s2 = s1[6 .. 11];	// s2 is "world"
+
+ + Slicing, of course, works with any array in D, not just strings. + +

Copying a String

+ + C++ copies strings with the replace function: + +
	string s1 = "hello world";
+	string s2 = "goodbye      ";
+	s2.replace(8, 5, s1, 6, 5);	// s2 is "goodbye world"
+
+ + D uses the slice syntax as an lvalue: + +
	char[] s1 = "hello world";
+	char[] s2 = "goodbye      ";
+	s2[8..13] = s1[6..11];		// s2 is "goodbye world"
+
+ +

Conversions to C Strings

+ + This is needed for compatibility with C API's. In C++, this + uses the c_str() member function: + +
	void foo(const char *);
+	string s1;
+	foo(s1.c_str());
+
+ + In D, strings can be implicitly converted to char*: + +
	void foo(char *);
+	char[] s1;
+	foo(s1);
+
+ + Note: some will argue that it is a mistake in D to have an implicit + conversion from char[] to char*. + +

Array Bounds Checking

+ + In C++, string array bounds checking for [] is not done. + In D, array bounds checking is on by default and it can be turned off + with a compiler switch after the program is debugged. + +

String Switch Statements

+ + Are not possible in C++, nor is there any way to add them + by adding more to the library. In D, they take the obvious + syntactical forms: + +
	switch (str)
+	{
+	    case "hello":
+	    case "world":
+		...
+	}
+
+ + where str can be any of literal "string"s, fixed string arrays + like char[10], or dynamic strings like char[]. A quality implementation + can, of course, explore many strategies of efficiently implementing + this based on the contents of the case strings. + +

Filling a String

+ + In C++, this is done with the replace() member function: + +
	string str = "hello";
+	str.replace(1,2,2,'?');		// str is "h??lo"
+
+ + In D, use the array slicing syntax in the natural manner: + +
	char[] str = "hello";
+	str[1..2] = '?';		// str is "h??lo"
+
+ +

Value vs Reference

+ + C++ strings, as implemented by STLport, are by value and are + 0-terminated. [The latter is an implementation choice, but + STLport seems to be the most popular implementation.] + This, coupled with no garbage collection, has + some consequences. First of all, any string created must make + its own copy of the string data. The 'owner' of the string + data must be kept track of, because when the owner is deleted + all references become invalid. If one tries to avoid the + dangling reference problem by treating strings as value types, + there will be a lot of overhead of memory allocation, + data copying, and memory deallocation. Next, the 0-termination + implies that strings cannot refer to other strings. String + data in the data segment, stack, etc., cannot + be referred to. +

+ + D strings are reference types, and the memory is garbage collected. + This means that only references need to be copied, not the + string data. D strings can refer to data in the static data + segment, data on the stack, data inside other strings, objects, + file buffers, etc. There's no need to keep track of the 'owner' + of the string data. +

+ + The obvious question is if multiple D strings refer to the same + string data, what happens if the data is modified? All the + references will now point to the modified data. This can have + its own consequences, which can be avoided if the copy-on-write + convention is followed. All copy-on-write is is that if + a string is written to, an actual copy of the string data is made + first. +

+ + The result of D strings being reference only and garbage collected + is that code that does a lot of string manipulating, such as + an lzw compressor, can be a lot more efficient in terms of both + memory consumption and speed. + +

Benchmark

+ + Let's take a look at a small utility, wordcount, that counts up + the frequency of each word in a text file. In D, it looks like this: + +
import file;
+
+int main (char[][] args)
+{
+    int w_total;
+    int l_total;
+    int c_total;
+    int[char[]] dictionary;
+
+    printf("   lines   words   bytes file\n");
+    for (int i = 1; i < args.length; ++i)
+    {
+	char[] input;
+	int w_cnt, l_cnt, c_cnt;
+	int inword;
+	int wstart;
+
+	input = cast(char[])file.read(args[i]);
+
+	for (int j = 0; j < input.length; j++)
+	{   char c;
+
+	    c = input[j];
+	    if (c == '\n')
+		++l_cnt;
+	    if (c >= '0' && c <= '9')
+	    {
+	    }
+	    else if (c >= 'a' && c <= 'z' ||
+		c >= 'A' && c <= 'Z')
+	    {
+		if (!inword)
+		{
+		    wstart = j;
+		    inword = 1;
+		    ++w_cnt;
+		}
+	    }
+	    else if (inword)
+	    {   char[] word = input[wstart .. j];
+
+		dictionary[word]++;
+		inword = 0;
+	    }
+	    ++c_cnt;
+	}
+	if (inword)
+	{   char[] w = input[wstart .. input.length];
+	    dictionary[w]++;
+	}
+	printf("%8lu%8lu%8lu %.*s\n", l_cnt, w_cnt, c_cnt, args[i]);
+	l_total += l_cnt;
+	w_total += w_cnt;
+	c_total += c_cnt;
+    }
+
+    if (args.length > 2)
+    {
+	printf("--------------------------------------\n%8lu%8lu%8lu total",
+	    l_total, w_total, c_total);
+    }
+
+    printf("--------------------------------------\n");
+
+    foreach (char[] word1; dictionary.keys.sort)
+    {
+	printf("%3d %.*s\n", dictionary[word1], word1);
+    }
+    return 0;
+}
+
+ +

Two people have written C++ implementations using the C++ standard + template library, + wccpp1 + and + wccpp2. + The input file + alice30.txt + is the text of "Alice in Wonderland." + The D compiler, + dmd, + and the C++ compiler, + dmc, + share the same + optimizer and code generator, which provides a more apples to + apples comparison of the efficiency of the semantics of the languages + rather than the optimization and code generator sophistication. + Tests were run on a Win XP machine. dmc uses STLport for the template + implementation. +

+ + + + + + +
Program + Compile + Compile Time + Run + Run Time +
D wc + dmd wc -O -release + 0.0719 + wc alice30.txt >log + 0.0326 +
C++ wccpp1 + dmc wccpp1 -o -I\dm\stlport\stlport + 2.1917 + wccpp1 alice30.txt >log + 0.0944 +
C++ wccpp2 + dmc wccpp2 -o -I\dm\stlport\stlport + 2.0463 + wccpp2 alice30.txt >log + 0.1012 +
+ +

The following tests were run on linux, again comparing a D compiler + (gdc) + and a C++ compiler (g++) that share a common optimizer and + code generator. The system is Pentium III 800MHz running RedHat Linux 8.0 + and gcc 3.4.2. + The Digital Mars D compiler for linux (dmd) + is included for comparison. +

+ + + + + + + + +
Program + Compile + Compile Time + Run + Run Time +
D wc + gdc -O2 -frelease -o wc wc.d + 0.326 + wc alice30.txt > /dev/null + 0.041 +
D wc + dmd wc -O -release + 0.235 + wc alice30.txt > /dev/null + 0.041 +
C++ wccpp1 + g++ -O2 -o wccpp1 wccpp1.cc + 2.874 + wccpp1 alice30.txt > /dev/null + 0.086 +
C++ wccpp2 + g++ -O2 -o wccpp2 wccpp2.cc + 2.886 + wccpp2 alice30.txt > /dev/null + 0.095 +
+ +

These tests compare gdc with g++ on a PowerMac G5 2x2.0GHz + running MacOS X 10.3.5 and gcc 3.4.2. (Timings are a little + less accurate.) +

+ + + + + + +
Program + Compile + Compile Time + Run + Run Time +
D wc + gdc -O2 -frelease -o wc wc.d + 0.28 + wc alice30.txt > /dev/null + 0.03 +
C++ wccpp1 + g++ -O2 -o wccpp1 wccpp1.cc + 1.90 + wccpp1 alice30.txt > /dev/null + 0.07 +
C++ wccpp2 + g++ -O2 -o wccpp2 wccpp2.cc + 1.88 + wccpp2 alice30.txt > /dev/null + 0.08 +
+
+

wccpp2 by Allan Odgaard

+ +
#include <algorithm>
+#include <cstdio>
+#include <fstream>
+#include <iterator>
+#include <map>
+#include <vector>
+
+bool isWordStartChar (char c)	{ return isalpha(c); }
+bool isWordEndChar (char c)	{ return !isalnum(c); }
+
+int main (int argc, char const* argv[])
+{
+    using namespace std;
+    printf("Lines Words Bytes File:\n");
+
+    map<string, int> dict;
+    int tLines = 0, tWords = 0, tBytes = 0;
+    for(int i = 1; i < argc; i++)
+    {
+	ifstream file(argv[i]);
+	istreambuf_iterator<char> from(file.rdbuf()), to;
+	vector<char> v(from, to);
+	vector<char>::iterator first = v.begin(), last = v.end(), bow, eow;
+
+	int numLines = count(first, last, '\n');
+	int numWords = 0;
+	int numBytes = last - first;
+
+	for(eow = first; eow != last; )
+	{
+	    bow = find_if(eow, last, isWordStartChar);
+	    eow = find_if(bow, last, isWordEndChar);
+	    if(bow != eow)
+		++dict[string(bow, eow)], ++numWords;
+	}
+
+	printf("%5d %5d %5d %s\n", numLines, numWords, numBytes, argv[i]);
+
+	tLines += numLines;
+	tWords += numWords;
+	tBytes += numBytes;
+    }
+
+    if(argc > 2)
+	    printf("-----------------------\n%5d %5d %5d\n", tLines, tWords, tBytes);
+    printf("-----------------------\n\n");
+
+    for(map<string, int>::const_iterator it = dict.begin(); it != dict.end(); ++it)
+	    printf("%5d %s\n", it->second, it->first.c_str());
+
+    return 0;
+}
+
+ + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/cpptod.html dmd-0.136/dmd/html/d/cpptod.html --- dmd-0.135/dmd/html/d/cpptod.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/cpptod.html 2005-10-04 18:05:28.000000000 +0200 @@ -1,881 +1,865 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Digital Mars - Programming in D for C++ Programmers - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- -D vs C/C++/C#/Java

-Rationale for Builtins

-Converting C to D

-Converting C++ to D

-The C Preprocessor vs D

-D strings vs C++ std::string

-D complex vs C++ std::complex

-D Contract Programming vs C++

-
-
- - -

Programming in D for C++ Programmers

- -C++ - -Every experienced C++ programmer accumulates a series of idioms and techniques -which become second nature. Sometimes, when learning a new language, those -idioms can be so comfortable it's hard to see how to do the equivalent in the -new language. So here's a collection of common C++ techniques, and how to do the -corresponding task in D. -

- -See also: Programming in D for C Programmers - -

- - -
- -

Defining constructors

- -

The C++ Way

- - Constructors have the same name as the class: - -
-	class Foo
-	{
-		Foo(int x); 
-	};
- -

The D Way

- - Constructors are defined with the this keyword: - -
-	class Foo
-	{
-		this(int x) { } 
-	}
- - which reflects how they are used in D. - -
-

Base class initialization

- -

The C++ Way

- - Base constructors are called using the base initializer syntax. - -
-	class A { A() {... } };
-	class B : A
-	{
-	     B(int x)
-		: A()		// call base constructor 
-	     {	...
-	     }
-	};
- -

The D Way

- - The base class constructor is called with the super syntax: - -
-	class A { this() { ... } }
-	class B : A
-	{
-	     this(int x)
-	     {	...
-		super();	// call base constructor 
-		...
-	     }
-	}
- - It's superior to C++ in that the base constructor call can be flexibly placed anywhere in the derived - constructor. D can also have one constructor call another one: - -
-	class A
-	{	int a;
-		int b;
-		this() { a = 7; b = foo(); } 
-		this(int x)
-		{
-		    this();
-		    a = x;
-		}
-	}
- - Members can also be initialized to constants before the constructor is ever called, so the above example is - equivalently written as: - -
-	class A
-	{	int a = 7;
-		int b;
-		this() { b = foo(); } 
-		this(int x)
-		{
-		    this();
-		    a = x;
-		}
-	}
- -
-

Comparing structs

- -

The C++ Way

- - While C++ defines struct assignment in a simple, convenient manner: - -
-	struct A x, y; 
-	...
-	x = y;
-	
- - it does not for struct comparisons. Hence, to compare two struct - instances for equality: - -
-	#include <string.h>
-
-	struct A x, y;
-
-	inline bool operator==(const A& x, const A& y)
-	{
-	    return (memcmp(&x, &y, sizeof(struct A)) == 0); 
-	}
-	...
-	if (x == y)
-	    ...
-	
- - Note that the operator overload must be done for every struct - needing to be compared, and the implementation of that overloaded - operator is free of any language help with type checking. - The C++ way has an additional problem in that just inspecting the - (x == y) does not give a clue what is actually happening, you have - to go and find the particular overloaded operator==() that applies - to verify what it really does. -

- - There's a nasty bug lurking in the memcmp() implementation of operator==(). - The layout of a struct, due to alignment, can have 'holes' in it. - C++ does not guarantee those holes are assigned any values, and so - two different struct instances can have the same value for each member, - but compare different because the holes contain different garbage. -

- - To address this, the operator==() can be implemented to do a memberwise - compare. Unfortunately, this is unreliable because (1) if a member is added - to the struct definition one may forget to add it to operator==(), and - (2) floating point nan values compare unequal even if their bit patterns - match. -

- - There just is no robust solution in C++. - -

The D Way

- - D does it the obvious, straightforward way: - -
-	A x, y;
-	...
-	if (x == y) 
-	    ...
-	
- -
-

Creating a new typedef'd type

- -

The C++ Way

- - Typedef's in C++ are weak, that is, they really do not introduce - a new type. The compiler doesn't distinguish between a typedef - and its underlying type. - -
-	#define HANDLE_INIT	((Handle)(-1))
-	typedef void *Handle;
-	void foo(void *);
-	void bar(Handle);
-
-	Handle h = HANDLE_INIT;
-	foo(h);			// coding bug not caught 
-	bar(h);			// ok
-	
- - The C++ solution is to create a dummy struct whose sole - purpose is to get type checking and overloading on the new type. - -
-	#define HANDLE_INIT	((void *)(-1)) 
-	struct Handle
-	{   void *ptr;
-
-	    // default initializer
-	    Handle() { ptr = HANDLE_INIT; }
-
-	    Handle(int i) { ptr = (void *)i; }
-
-	    // conversion to underlying type 
-	    operator void*() { return ptr; }
-	};
-	void bar(Handle);
-
-	Handle h;
-	bar(h);
-	h = func();
-	if (h != HANDLE_INIT)
-	    ...
-	
- -

The D Way

- - No need for idiomatic constructions like the above. Just write: - -
-	typedef void *Handle = cast(void *)-1; 
-	void bar(Handle);
-
-	Handle h;
-	bar(h);
-	h = func();
-	if (h != Handle.init)
-	    ...
-	
- - Note how a default initializer can be supplied for the typedef as - a value of the underlying type. - -
-

Friends

- -

The C++ Way

- - Sometimes two classes are tightly related but not by inheritance, - but need to access each other's private members. This is done - using friend declarations: - -
-	class A
-	{
-	    private:
-		int a;
-
-	    public:
-		int foo(B *j);
-		friend class B;
-		friend int abc(A *);
-	};
-
-	class B
-	{
-	    private:
-		int b;
-
-	    public:
-		int bar(A *j);
-		friend class A;
-	};
-
-	int A::foo(B *j) { return j->b; }
-	int B::bar(A *j) { return j->a; } 
-
-	int abc(A *p) { return p->a; }
-	
- -

The D Way

- - In D, friend access is implicit in being a member of the same - module. It makes sense that tightly related classes should be - in the same module, so implicitly granting friend access to - other module members solves the problem neatly: - -
-	module X;
-
-	class A
-	{
-	    private:
-		static int a;
-
-	    public:
-		int foo(B j) { return j.b; }
-	}
-
-	class B
-	{
-	    private:
-		static int b;
-
-	    public:
-		int bar(A j) { return j.a; } 
-	}
-
-	int abc(A p) { return p.a; }
-	
- - The private attribute prevents other modules from - accessing the members. - -
-

Operator overloading

- -

The C++ Way

- - Given a struct that creates a new arithmetic data type, - it's convenient to overload the comparison operators so - it can be compared against integers: - -
-	struct A
-	{
-		int operator <  (int i);
-		int operator <= (int i);
-		int operator >  (int i);
-		int operator >= (int i);
-	};
-
-	int operator <  (int i, A &a) { return a >  i; }
-	int operator <= (int i, A &a) { return a >= i; }
-	int operator >  (int i, A &a) { return a <  i; }
-	int operator >= (int i, A &a) { return a <= i; } 
-	
- - A total of 8 functions are necessary. - -

The D Way

- - D recognizes that the comparison operators are all fundamentally - related to each other. So only one function is necessary: - -
-	struct A
-	{
-		int opCmp(int i); 
-	}
-	
- - The compiler automatically interprets all the - <, <=, > and >= - operators in terms of the cmp function, as well - as handling the cases where the left operand is not an - object reference. -

- - Similar sensible rules hold for other operator overloads, - making using operator overloading in D much less tedious and less - error prone. Far less code needs to be written to accomplish - the same effect. - -


-

Namespace using declarations

- -

The C++ Way

- - A using-declaration in C++ is used to bring a name from - a namespace scope into the current scope: - -
-	namespace Foo 
-	{
-	    int x;
-	}
-	using Foo::x;
-	
- -

The D Way

- - D uses modules instead of namespaces and #include files, and - alias declarations take the place of using declarations: - -
-	---- Module Foo.d ------
-	module Foo;
-	int x;
-
-	---- Another module ---- 
-	import Foo;
-	alias Foo.x x;
-	
- - Alias is a much more flexible than the single purpose using - declaration. Alias can be used to rename symbols, refer to - template members, refer to nested class types, etc. - -
-

RAII (Resource Acquisition Is Initialization)

- -

The C++ Way

- - In C++, resources like memory, etc., all need to be handled - explicitly. Since destructors automatically get called when - leaving a scope, RAII is implemented by putting the resource - release code into the destructor: - -
-	class File
-	{   Handle *h;
-
-	    ~File()
-	    {
-		h->release(); 
-	    }
-	};
-	
- -

The D Way

- - The bulk of resource release problems are simply keeping track - of and freeing memory. This is handled automatically in D by - the garbage collector. The second common resources used are semaphores - and locks, handled automatically with D's synchronized - declarations and statements. -

- - The few RAII issues left are handled by auto classes. - Auto classes get their destructors run when they go out of scope. - -

-	auto class File
-	{   Handle h;
-
-	    ~this()
-	    {
-		h.release();
-	    }
-	}
-
-	void test()
-	{
-	    if (...)
-	    {   auto File f = new File();
-		...
-	    } // f.~this() gets run at closing brace, even if 
-	      // scope was exited via a thrown exception
-	}
-	
- -
-

Properties

- -

The C++ Way

- - It is common practice to define a field, - along with object-oriented - get and set functions for it: - -
-	class Abc
-	{
-	  public:
-	    void setProperty(int newproperty) { property = newproperty; } 
-	    int getProperty() { return property; }
-
-	  private:
-	    int property;
-	};
-
-	Abc a;
-	a.setProperty(3);
-	int x = a.getProperty();
-	
- - All this is quite a bit of typing, and it tends to make - code unreadable by filling - it with getProperty() and setProperty() calls. - -

The D Way

- - Properties can be get and set using the normal field syntax, - yet the get and set will invoke methods instead. - -
-	class Abc
-	{
-	    // set 
-	    void property(int newproperty) { myprop = newproperty; }
-
-	    // get
-	    int property() { return myprop; }
-
-	  private:
-	    int myprop;
-	}
-	
- - which is used as: - -
-	Abc a;
-	a.property = 3;		// equivalent to a.property(3)
-	int x = a.property;	// equivalent to int x = a.property() 
-	
- - Thus, in D a property can be treated like it was a simple field name. - A property can start out actually being a simple field name, - but if later if becomes - necessary to make getting and setting it function calls, - no code needs to be modified other - than the class definition. - It obviates the wordy practice of defining get and set properties - 'just in case' a derived class should need to override them. - It's also a way to have interface classes, which do not have - data fields, behave syntactically as if they did. - -
-

Recursive Templates

- -

The C++ Way

- - An advanced use of templates is to recursively expand - them, relying on specialization to end it. A template - to compute a factorial would be: - -
-	template<int n> class factorial
-	{
-	    public:
-		enum { result = n * factorial<n - 1>::result }; 
-	};
-
-	template<> class factorial<1>
-	{
-	    public:
-		enum { result = 1 };
-	};
-
-	void test()
-	{
-	    printf("%d\n", factorial<4>::result); // prints 24
-	}
- -

The D Way

- - The D version is analogous, though a little simpler, taking - advantage of promotion of single template members to the - enclosing name space: - -
-	template factorial(int n)
-	{
-	    enum { factorial = n* .factorial!(n-1) }
-	}
-
-	template factorial(int n : 1)
-	{
-	    enum { factorial = 1 }
-	}
-
-	void test()
-	{
-	    printf("%d\n", factorial!(4));	// prints 24 
-	}
- -
- -

Meta Templates

- - The problem: create a typedef for a signed integral type that is at - least nbits in size. - -

The C++ Way

- - This example is simplified and adapted from one written by - Dr. Carlo Pescio in - - Template Metaprogramming: Make parameterized integers portable with this novel technique. -

- - There is no way in C++ to do conditional compilation based - on the result of an expression based on template parameters, so - all control flow follows from pattern matching of the template - argument against various explicit template specializations. - Even worse, there is no way to do template specializations based - on relationships like "less than or equal to", so the example - uses a clever technique where the template is recursively expanded, - incrementing the template value argument by one each time, until - a specialization matches. - If there is no match, the result is an unhelpful recursive compiler - stack overflow or internal error, or at best a strange syntax - error. -

- - A preprocessor macro is also needed to make up for the lack - of template typedefs. - -

-	#include <limits.h>
-
-	template< int nbits > struct Integer
-	{
-	    typedef Integer< nbits + 1 > :: int_type int_type ;
-	} ;
-
-	struct Integer< 8 >
-	{
-	    typedef signed char int_type ;
-	} ;
-
-	struct Integer< 16 > 
-	{
-	    typedef short int_type ;
-	} ;
-
-	struct Integer< 32 > 
-	{
-	    typedef int int_type ;
-	} ;
-
-	struct Integer< 64 >
-	{
-	    typedef long long int_type ;
-	} ;
-
-	// If the required size is not supported, the metaprogram
-	// will increase the counter until an internal error is
-	// signaled, or INT_MAX is reached. The INT_MAX 
-	// specialization does not define a int_type, so a 
-	// compiling error is always generated
-	struct Integer< INT_MAX >
-	{
-	} ;
-
-	// A bit of syntactic sugar
-	#define Integer( nbits ) Integer< nbits > :: int_type 
-
-	#include <stdio.h>
-
-	int main()
-	{
-	    Integer( 8 ) i ;
-	    Integer( 16 ) j ;
-	    Integer( 29 ) k ;
-	    Integer( 64 ) l ;
-	    printf("%d %d %d %d\n",
-		sizeof(i), sizeof(j), sizeof(k), sizeof(l)); 
-	    return 0 ;
-	}
- - -

The D Way

- - The D version could also be written with recursive templates, - but there's a better way. - Unlike the C++ example, this one is fairly easy to - figure out what is going on. - It compiles quickly, and gives a sensible compile time message - if it fails. - -
-	template Integer(int nbits)
-	{
-	    static if (nbits <= 8)
-		alias byte Integer;
-	    else static if (nbits <= 16)
-		alias short Integer;
-	    else static if (nbits <= 32)
-		alias int Integer;
-	    else static if (nbits <= 64)
-		alias long Integer;
-	    else
-		static assert(0);
-	}
-
-	int main()
-	{
-	    Integer!(8) i ;
-	    Integer!(16) j ;
-	    Integer!(29) k ;
-	    Integer!(64) l ;
-	    printf("%d %d %d %d\n",
-		i.sizeof, j.sizeof, k.sizeof, l.sizeof); 
-	    return 0;
-	}
- -
- -

Type Traits

- - Type traits are another term for being able to find out - properties of a type at compile time. - -

The C++ Way

- - The following template comes from - - C++ Templates: The Complete Guide, David Vandevoorde, Nicolai M. Josuttis - pg. 353 which determines if the template's argument type - is a function: - -
-	template<typename T> class IsFunctionT
-	{
-	    private:
-		typedef char One;
-		typedef struct { char a[2]; } Two;
-		template<typename U> static One test(...);
-		template<typename U> static Two test(U (*)[1]);
-	    public:
-		enum { Yes = sizeof(IsFunctionT<T>::test<T>(0)) == 1 };
-	};
-
-	void test()
-	{
-	    typedef int (fp)(int);
-
-	    assert(IsFunctionT<fp>::Yes == 1);
-	}
-	
- - This template relies on the - SFINAE - (Substitution Failure Is Not An Error) principle. - Why it works is a fairly advanced template topic. - -

The D Way

- - SFINAE can be done in D without resorting to template argument - pattern matching: - -
-	template IsFunctionT(T)
-	{
-	    static if ( is(T[]) )
-		const int IsFunctionT = 1;
-	    else
-		const int IsFunctionT = 0;
-	}
-
-	void test()
-	{
-	    typedef int fp(int);
-
-	    assert(IsFunctionT!(fp) == 1);
-	}
-	
- - The task of discovering if a type is a function doesn't need a - template at all, nor does it need the subterfuge of attempting to - create the invalid array of functions type. - The is - expression can test it directly: - -
-	void test()
-	{
-	    typedef int fp(int);
-
-	    assert( is(fp == function) );
-	}
-	
- - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +Digital Mars - Programming in D for C++ Programmers + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:28 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· D vs C/C++/C#/Java
+ + +· Rationale for Builtins
+ + +· Converting C to D
+ + +· Converting C++ to D
+ + +· The C Preprocessor vs D
+ + +· D strings vs C++ std::string
+ + +· D complex vs C++ std::complex
+ + +· D Contract Programming vs C++
+ + +
+
+ +

Programming in D for C++ Programmers

+ +C++ + +Every experienced C++ programmer accumulates a series of idioms and techniques +which become second nature. Sometimes, when learning a new language, those +idioms can be so comfortable it's hard to see how to do the equivalent in the +new language. So here's a collection of common C++ techniques, and how to do the +corresponding task in D. +

+ +See also: Programming in D for C Programmers + +

+ + +
+ +

Defining constructors

+ +

The C++ Way

+ + Constructors have the same name as the class: + +
class Foo
+{
+	Foo(int x); 
+};
+
+ +

The D Way

+ + Constructors are defined with the this keyword: + +
class Foo
+{
+	this(int x) { } 
+}
+
+ + which reflects how they are used in D. + +
+

Base class initialization

+ +

The C++ Way

+ + Base constructors are called using the base initializer syntax. + +
class A { A() {... } };
+class B : A
+{
+     B(int x)
+	: A()		// call base constructor 
+     {	...
+     }
+};
+ +

The D Way

+ + The base class constructor is called with the super syntax: + +
class A { this() { ... } }
+class B : A
+{
+     this(int x)
+     {	...
+	super();	// call base constructor 
+	...
+     }
+}
+
+ + It's superior to C++ in that the base constructor call can be flexibly placed anywhere in the derived + constructor. D can also have one constructor call another one: + +
class A
+{	int a;
+	int b;
+	this() { a = 7; b = foo(); } 
+	this(int x)
+	{
+	    this();
+	    a = x;
+	}
+}
+
+ + Members can also be initialized to constants before the constructor is ever called, so the above example is + equivalently written as: + +
class A
+{	int a = 7;
+	int b;
+	this() { b = foo(); } 
+	this(int x)
+	{
+	    this();
+	    a = x;
+	}
+}
+
+ +
+

Comparing structs

+ +

The C++ Way

+ + While C++ defines struct assignment in a simple, convenient manner: + +
struct A x, y; 
+...
+x = y;
+
+ + it does not for struct comparisons. Hence, to compare two struct + instances for equality: + +
#include <string.h>
+
+struct A x, y;
+
+inline bool operator==(const A& x, const A& y)
+{
+    return (memcmp(&x, &y, sizeof(struct A)) == 0); 
+}
+...
+if (x == y)
+    ...
+
+ + Note that the operator overload must be done for every struct + needing to be compared, and the implementation of that overloaded + operator is free of any language help with type checking. + The C++ way has an additional problem in that just inspecting the + (x == y) does not give a clue what is actually happening, you have + to go and find the particular overloaded operator==() that applies + to verify what it really does. +

+ + There's a nasty bug lurking in the memcmp() implementation of operator==(). + The layout of a struct, due to alignment, can have 'holes' in it. + C++ does not guarantee those holes are assigned any values, and so + two different struct instances can have the same value for each member, + but compare different because the holes contain different garbage. +

+ + To address this, the operator==() can be implemented to do a memberwise + compare. Unfortunately, this is unreliable because (1) if a member is added + to the struct definition one may forget to add it to operator==(), and + (2) floating point nan values compare unequal even if their bit patterns + match. +

+ + There just is no robust solution in C++. + +

The D Way

+ + D does it the obvious, straightforward way: + +
A x, y;
+...
+if (x == y) 
+    ...
+
+ +
+

Creating a new typedef'd type

+ +

The C++ Way

+ + Typedef's in C++ are weak, that is, they really do not introduce + a new type. The compiler doesn't distinguish between a typedef + and its underlying type. + +
#define HANDLE_INIT	((Handle)(-1))
+typedef void *Handle;
+void foo(void *);
+void bar(Handle);
+
+Handle h = HANDLE_INIT;
+foo(h);			// coding bug not caught 
+bar(h);			// ok
+
+ + The C++ solution is to create a dummy struct whose sole + purpose is to get type checking and overloading on the new type. + +
#define HANDLE_INIT	((void *)(-1)) 
+struct Handle
+{   void *ptr;
+
+    // default initializer
+    Handle() { ptr = HANDLE_INIT; }
+
+    Handle(int i) { ptr = (void *)i; }
+
+    // conversion to underlying type 
+    operator void*() { return ptr; }
+};
+void bar(Handle);
+
+Handle h;
+bar(h);
+h = func();
+if (h != HANDLE_INIT)
+    ...
+
+ +

The D Way

+ + No need for idiomatic constructions like the above. Just write: + +
typedef void *Handle = cast(void *)-1; 
+void bar(Handle);
+
+Handle h;
+bar(h);
+h = func();
+if (h != Handle.init)
+    ...
+
+ + Note how a default initializer can be supplied for the typedef as + a value of the underlying type. + +
+

Friends

+ +

The C++ Way

+ + Sometimes two classes are tightly related but not by inheritance, + but need to access each other's private members. This is done + using friend declarations: + +
class A
+{
+    private:
+	int a;
+
+    public:
+	int foo(B *j);
+	friend class B;
+	friend int abc(A *);
+};
+
+class B
+{
+    private:
+	int b;
+
+    public:
+	int bar(A *j);
+	friend class A;
+};
+
+int A::foo(B *j) { return j->b; }
+int B::bar(A *j) { return j->a; } 
+
+int abc(A *p) { return p->a; }
+
+ +

The D Way

+ + In D, friend access is implicit in being a member of the same + module. It makes sense that tightly related classes should be + in the same module, so implicitly granting friend access to + other module members solves the problem neatly: + +
module X;
+
+class A
+{
+    private:
+	static int a;
+
+    public:
+	int foo(B j) { return j.b; }
+}
+
+class B
+{
+    private:
+	static int b;
+
+    public:
+	int bar(A j) { return j.a; } 
+}
+
+int abc(A p) { return p.a; }
+
+ + The private attribute prevents other modules from + accessing the members. + +
+

Operator overloading

+ +

The C++ Way

+ + Given a struct that creates a new arithmetic data type, + it's convenient to overload the comparison operators so + it can be compared against integers: + +
struct A
+{
+	int operator <  (int i);
+	int operator <= (int i);
+	int operator >  (int i);
+	int operator >= (int i);
+};
+
+int operator <  (int i, A &a) { return a >  i; }
+int operator <= (int i, A &a) { return a >= i; }
+int operator >  (int i, A &a) { return a <  i; }
+int operator >= (int i, A &a) { return a <= i; } 
+
+ + A total of 8 functions are necessary. + +

The D Way

+ + D recognizes that the comparison operators are all fundamentally + related to each other. So only one function is necessary: + +
struct A
+{
+	int opCmp(int i); 
+}
+
+ + The compiler automatically interprets all the + <, <=, > and >= + operators in terms of the cmp function, as well + as handling the cases where the left operand is not an + object reference. +

+ + Similar sensible rules hold for other operator overloads, + making using operator overloading in D much less tedious and less + error prone. Far less code needs to be written to accomplish + the same effect. + +


+

Namespace using declarations

+ +

The C++ Way

+ + A using-declaration in C++ is used to bring a name from + a namespace scope into the current scope: + +
namespace Foo 
+{
+    int x;
+}
+using Foo::x;
+
+ +

The D Way

+ + D uses modules instead of namespaces and #include files, and + alias declarations take the place of using declarations: + +
/** Module Foo.d **/
+module Foo;
+int x;
+
+/** Another module **/ 
+import Foo;
+alias Foo.x x;
+
+ + Alias is a much more flexible than the single purpose using + declaration. Alias can be used to rename symbols, refer to + template members, refer to nested class types, etc. + +
+

RAII (Resource Acquisition Is Initialization)

+ +

The C++ Way

+ + In C++, resources like memory, etc., all need to be handled + explicitly. Since destructors automatically get called when + leaving a scope, RAII is implemented by putting the resource + release code into the destructor: + +
class File
+{   Handle *h;
+
+    ~File()
+    {
+	h->release(); 
+    }
+};
+
+ +

The D Way

+ + The bulk of resource release problems are simply keeping track + of and freeing memory. This is handled automatically in D by + the garbage collector. The second common resources used are semaphores + and locks, handled automatically with D's synchronized + declarations and statements. +

+ + The few RAII issues left are handled by auto classes. + Auto classes get their destructors run when they go out of scope. + +

auto class File
+{   Handle h;
+
+    ~this()
+    {
+	h.release();
+    }
+}
+
+void test()
+{
+    if (...)
+    {   auto File f = new File();
+	...
+    } // f.~this() gets run at closing brace, even if 
+      // scope was exited via a thrown exception
+}
+
+ +
+

Properties

+ +

The C++ Way

+ + It is common practice to define a field, + along with object-oriented + get and set functions for it: + +
class Abc
+{
+  public:
+    void setProperty(int newproperty) { property = newproperty; } 
+    int getProperty() { return property; }
+
+  private:
+    int property;
+};
+
+Abc a;
+a.setProperty(3);
+int x = a.getProperty();
+
+ + All this is quite a bit of typing, and it tends to make + code unreadable by filling + it with getProperty() and setProperty() calls. + +

The D Way

+ + Properties can be get and set using the normal field syntax, + yet the get and set will invoke methods instead. + +
class Abc
+{
+    // set 
+    void property(int newproperty) { myprop = newproperty; }
+
+    // get
+    int property() { return myprop; }
+
+  private:
+    int myprop;
+}
+
+ + which is used as: + +
Abc a;
+a.property = 3;		// equivalent to a.property(3)
+int x = a.property;	// equivalent to int x = a.property() 
+
+ + Thus, in D a property can be treated like it was a simple field name. + A property can start out actually being a simple field name, + but if later if becomes + necessary to make getting and setting it function calls, + no code needs to be modified other + than the class definition. + It obviates the wordy practice of defining get and set properties + 'just in case' a derived class should need to override them. + It's also a way to have interface classes, which do not have + data fields, behave syntactically as if they did. + +
+

Recursive Templates

+ +

The C++ Way

+ + An advanced use of templates is to recursively expand + them, relying on specialization to end it. A template + to compute a factorial would be: + +
template<int n> class factorial
+{
+    public:
+	enum { result = n * factorial<n - 1>::result }; 
+};
+
+template<> class factorial<1>
+{
+    public:
+	enum { result = 1 };
+};
+
+void test()
+{
+    printf("%d\n", factorial<4>::result); // prints 24
+}
+
+ +

The D Way

+ + The D version is analogous, though a little simpler, taking + advantage of promotion of single template members to the + enclosing name space: + +
template factorial(int n)
+{
+    enum { factorial = n * .factorial!(n-1) }
+}
+
+template factorial(int n : 1)
+{
+    enum { factorial = 1 }
+}
+
+void test()
+{
+    printf("%d\n", factorial!(4));	// prints 24 
+}
+
+ +
+ +

Meta Templates

+ + The problem: create a typedef for a signed integral type that is at + least nbits in size. + +

The C++ Way

+ + This example is simplified and adapted from one written by + Dr. Carlo Pescio in + + Template Metaprogramming: Make parameterized integers portable with this novel technique. +

+ + There is no way in C++ to do conditional compilation based + on the result of an expression based on template parameters, so + all control flow follows from pattern matching of the template + argument against various explicit template specializations. + Even worse, there is no way to do template specializations based + on relationships like "less than or equal to", so the example + uses a clever technique where the template is recursively expanded, + incrementing the template value argument by one each time, until + a specialization matches. + If there is no match, the result is an unhelpful recursive compiler + stack overflow or internal error, or at best a strange syntax + error. +

+ + A preprocessor macro is also needed to make up for the lack + of template typedefs. + +

#include <limits.h>
+
+template< int nbits > struct Integer
+{
+    typedef Integer< nbits + 1 > :: int_type int_type ;
+} ;
+
+struct Integer< 8 >
+{
+    typedef signed char int_type ;
+} ;
+
+struct Integer< 16 > 
+{
+    typedef short int_type ;
+} ;
+
+struct Integer< 32 > 
+{
+    typedef int int_type ;
+} ;
+
+struct Integer< 64 >
+{
+    typedef long long int_type ;
+} ;
+
+// If the required size is not supported, the metaprogram
+// will increase the counter until an internal error is
+// signaled, or INT_MAX is reached. The INT_MAX 
+// specialization does not define a int_type, so a 
+// compiling error is always generated
+struct Integer< INT_MAX >
+{
+} ;
+
+// A bit of syntactic sugar
+#define Integer( nbits ) Integer< nbits > :: int_type 
+
+#include <stdio.h>
+
+int main()
+{
+    Integer( 8 ) i ;
+    Integer( 16 ) j ;
+    Integer( 29 ) k ;
+    Integer( 64 ) l ;
+    printf("%d %d %d %d\n",
+	sizeof(i), sizeof(j), sizeof(k), sizeof(l)); 
+    return 0 ;
+}
+
+ + +

The D Way

+ + The D version could also be written with recursive templates, + but there's a better way. + Unlike the C++ example, this one is fairly easy to + figure out what is going on. + It compiles quickly, and gives a sensible compile time message + if it fails. + +
template Integer(int nbits)
+{
+    static if (nbits <= 8)
+	alias byte Integer;
+    else static if (nbits <= 16)
+	alias short Integer;
+    else static if (nbits <= 32)
+	alias int Integer;
+    else static if (nbits <= 64)
+	alias long Integer;
+    else
+	static assert(0);
+}
+
+int main()
+{
+    Integer!(8) i ;
+    Integer!(16) j ;
+    Integer!(29) k ;
+    Integer!(64) l ;
+    printf("%d %d %d %d\n",
+	i.sizeof, j.sizeof, k.sizeof, l.sizeof); 
+    return 0;
+}
+
+ +
+ +

Type Traits

+ + Type traits are another term for being able to find out + properties of a type at compile time. + +

The C++ Way

+ + The following template comes from + + C++ Templates: The Complete Guide, David Vandevoorde, Nicolai M. Josuttis + pg. 353 which determines if the template's argument type + is a function: + +
template<typename T> class IsFunctionT
+{
+    private:
+	typedef char One;
+	typedef struct { char a[2]; } Two;
+	template<typename U> static One test(...);
+	template<typename U> static Two test(U (*)[1]);
+    public:
+	enum { Yes = sizeof(IsFunctionT<T>::test<T>(0)) == 1 };
+};
+
+void test()
+{
+    typedef int (fp)(int);
+
+    assert(IsFunctionT<fp>::Yes == 1);
+}
+
+ + This template relies on the + SFINAE + (Substitution Failure Is Not An Error) principle. + Why it works is a fairly advanced template topic. + +

The D Way

+ + SFINAE can be done in D without resorting to template argument + pattern matching: + +
template IsFunctionT(T)
+{
+    static if ( is(T[]) )
+	const int IsFunctionT = 1;
+    else
+	const int IsFunctionT = 0;
+}
+
+void test()
+{
+    typedef int fp(int);
+
+    assert(IsFunctionT!(fp) == 1);
+}
+
+ + The task of discovering if a type is a function doesn't need a + template at all, nor does it need the subterfuge of attempting to + create the invalid array of functions type. + The is + expression can test it directly: + +
void test()
+{
+    typedef int fp(int);
+
+    assert( is(fp == function) );
+}
+
+ + + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/ctod.html dmd-0.136/dmd/html/d/ctod.html --- dmd-0.135/dmd/html/d/ctod.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/ctod.html 2005-10-04 18:05:28.000000000 +0200 @@ -1,1696 +1,1718 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Digital Mars - Programming in D for C Programmers - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- -D vs C/C++/C#/Java

-Rationale for Builtins

-Converting C to D

-Converting C++ to D

-The C Preprocessor vs D

-D strings vs C++ std::string

-D complex vs C++ std::complex

-D Contract Programming vs C++

-
-
- - -

Programming in D for C Programmers

- -ouch! - -Every experienced C programmer accumulates a series of idioms and techniques -which become second nature. Sometimes, when learning a new language, those -idioms can be so comfortable it's hard to see how to do the equivalent in the -new language. So here's a collection of common C techniques, and how to do the -corresponding task in D. -

- -Since C does not have object-oriented features, there's a separate section -for object-oriented issues -Programming in D for C++ Programmers. -

- -The C preprocessor is covered in -The C Preprocessor vs D. - -

- -
-

Getting the Size of a Type

- -

The C Way

- -
	sizeof(int)
-	sizeof(char *)
-	sizeof(double)
-	sizeof(struct Foo)
- -

The D Way

- -

Use the size property:

- -
        int.size
-        (char *).size
-        double.size
-        Foo.size
- -
- -

Get the max and min values of a type

- -

The C Way

- -
	#include <limits.h>
-	#include <math.h>
-
-	CHAR_MAX
-	CHAR_MIN
-	ULONG_MAX
-	DBL_MIN
-
- -

The D Way

- -
        char.max
-        char.min
-        ulong.max
-        double.min
-
- -
- -

Primitive Types

- -

C to D types

- -
        bool               =>        bit 
-        char               =>        char 
-        signed char        =>        byte 
-        unsigned char      =>        ubyte 
-        short              =>        short 
-        unsigned short     =>        ushort 
-        wchar_t            =>        wchar 
-        int                =>        int 
-        unsigned           =>        uint 
-        long               =>        int 
-        unsigned long      =>        uint 
-        long long          =>        long 
-        unsigned long long =>        ulong 
-        float              =>        float 
-        double             =>        double 
-        long double        =>        real 
-	_Imaginary long double =>    imaginary
-	_Complex long double   =>    complex
-
-
-

- Although char is an unsigned 8 bit type, and - wchar is an unsigned 16 bit type, they have their own separate types - in order to aid overloading and type safety. -

- Ints and unsigneds in C are of varying size; not so in D. - -


- -

Special Floating Point Values

- -

The C Way

- -
       #include <fp.h> 
-
-       NAN 
-       INFINITY 
-
-       #include <float.h> 
-
-       DBL_DIG 
-       DBL_EPSILON 
-       DBL_MANT_DIG 
-       DBL_MAX_10_EXP 
-       DBL_MAX_EXP 
-       DBL_MIN_10_EXP 
-       DBL_MIN_EXP 
-
- -

The D Way

- -
       double.nan 
-       double.infinity 
-       double.dig 
-       double.epsilon 
-       double.mant_dig 
-       double.max_10_exp 
-       double.max_exp 
-       double.min_10_exp 
-       double.min_exp 
-
- -
-

Remainder after division of floating point numbers

- -

The C Way

- -
-       #include <math.h> 
-
-       float f = fmodf(x,y); 
-       double d = fmod(x,y); 
-       long double e = fmodl(x,y); 
-
- -

The D Way

- -D supports the remainder ('%') operator on floating point operands: - -
-       float f = x % y; 
-       double d = x % y; 
-       extended e = x % y; 
-
- -
- -

Dealing with NAN's in floating point compares

- -

The C Way

- - C doesn't define what happens if an operand to a compare - is NAN, and few C compilers check for it (the Digital Mars - C compiler is an exception, DM's compilers do check for NAN operands). - -
-       #include <math.h> 
-
-       if (isnan(x) || isnan(y)) 
-	   result = FALSE; 
-       else 
-	   result = (x < y); 
-
- -

The D Way

-

- D offers a full complement of comparisons and operators - that work with NAN arguments. - -

       result = (x < y);        // false if x or y is nan 
-
- -
- -

Assert's are a necessary part of any good defensive coding strategy.

- -

The C Way

-

-C doesn't directly support assert, but does support __FILE__ -and __LINE__ from which an assert macro can be built. In fact, -there appears to be practically no other use for __FILE__ and __LINE__. - -

-       #include <assert.h> 
-
-       assert(e == 0); 
-
- -

The D Way

- -D simply builds assert into the language: - -
-       assert(e == 0); 
-
- -[NOTE: trace functions?] - -
- -

Initializing all elements of an array

- -

The C Way

- -
-       #define ARRAY_LENGTH        17 
-       int array[ARRAY_LENGTH]; 
-       for (i = 0; i < ARRAY_LENGTH; i++) 
-	   array[i] = value; 
-
- -

The D Way

- -
-       int array[17]; 
-       array[] = value; 
-
- -
- -

Looping through an array

- -

The C Way

-

- The array length is defined separately, or a clumsy - sizeof() expression is used to get the length. - -

-       #define ARRAY_LENGTH        17 
-       int array[ARRAY_LENGTH]; 
-       for (i = 0; i < ARRAY_LENGTH; i++) 
-	   func(array[i]); 
-
- -or: - -
-       int array[17]; 
-       for (i = 0; i < sizeof(array) / sizeof(array[0]); i++) 
-	   func(array[i]); 
-
- -

The D Way

- -The length of an array is accessible the property "length". - -
-       int array[17]; 
-       for (i = 0; i < array.length; i++) 
-	   func(array[i]); 
-
- -or even better: - -
-       int array[17]; 
-       foreach (int value; array)
-	   func(value); 
-
- - -
- -

Creating an array of variable size

- -

The C Way

- - C cannot do this with arrays. It is necessary to create a separate - variable for the length, and then explicitly manage the size of - the array: - -
-       #include <stdlib.h> 
-
-       int array_length; 
-       int *array; 
-       int *newarray; 
-
-       newarray = (int *)
-	   realloc(array, (array_length + 1) * sizeof(int)); 
-       if (!newarray) 
-	   error("out of memory"); 
-       array = newarray; 
-       array[array_length++] = x; 
-
- -

The D Way

- - D supports dynamic arrays, which can be easily resized. D supports - all the requisite memory management. - -
-       int[] array; 
-
-       array.length = array.length + 1;
-       array[array.length - 1] = x; 
-
- -
- -

String Concatenation

- -

The C Way

- - There are several difficulties to be resolved, like - when can storage be free'd, dealing with null pointers, - finding the length of the strings, and memory allocation: - -
 
-       #include <string.h> 
-
-       char *s1; 
-       char *s2; 
-       char *s; 
-
-       // Concatenate s1 and s2, and put result in s 
-       free(s); 
-       s = (char *)malloc((s1 ? strlen(s1) : 0) + 
-			  (s2 ? strlen(s2) : 0) + 1); 
-       if (!s) 
-	   error("out of memory"); 
-       if (s1) 
-	   strcpy(s, s1); 
-       else 
-	   *s = 0; 
-       if (s2) 
-	   strcpy(s + strlen(s), s2); 
-
-       // Append "hello" to s 
-       char hello[] = "hello"; 
-       char *news; 
-       size_t lens = s ? strlen(s) : 0; 
-       news = (char *)
-	   realloc(s, (lens + sizeof(hello) + 1) * sizeof(char)); 
-       if (!news) 
-	   error("out of memory"); 
-       s = news; 
-       memcpy(s + lens, hello, sizeof(hello)); 
-
- -

The D Way

- - D overloads the operators ~ and ~= for char and wchar arrays to mean - concatenate and append, respectively: - -
-       char[] s1; 
-       char[] s2; 
-       char[] s; 
-
-       s = s1 ~ s2; 
-       s ~= "hello"; 
-
- -
- -

Formatted printing

- -

The C Way

- - printf() is the general purpose formatted print routine: - -
-       #include <stdio.h> 
-
-       printf("Calling all cars %d times!\n", ntimes); 
-
- -

The D Way

- - What can we say? printf() rules: - -
-       import stdio; 
-
-       printf("Calling all cars %d times!\n", ntimes); 
-
- -
- -

Forward referencing functions

- -

The C Way

- - Functions cannot be forward referenced. Hence, to call a function - not yet encountered in the source file, it is necessary to insert - a function declaration lexically preceding the call. - -
-       void forwardfunc(); 
-
-       void myfunc() 
-       {   
-	   forwardfunc(); 
-       } 
-
-       void forwardfunc() 
-       {   
-	   ... 
-       } 
-
- -

The D Way

- - The program is looked at as a whole, and so not only is it not - necessary to code forward declarations, it is not even allowed! - D avoids the tedium and errors associated with writing forward - referenced function declarations twice. - Functions can be defined in any order. - -
-        void myfunc() 
-        {   
-	   forwardfunc(); 
-        } 
-
-        void forwardfunc() 
-        {   
-	   ... 
-        } 
-
- -
- -

Functions that have no arguments

- -

The C Way

- -
-       void function(void); 
-
- -

The D Way

- - D is a strongly typed language, so there is no need to explicitly - say a function takes no arguments, just don't declare it has having - arguments. - -
-       void function() 
-       {   
-	   ... 
-       } 
-
- -
- -

Labelled break's and continue's.

- -

The C Way

- - Break's and continue's only apply to the innermost nested loop or - switch, so a multilevel break must use a goto: - -
-               for (i = 0; i < 10; i++) 
-               { 
-                   for (j = 0; j < 10; j++) 
-                   { 
-                       if (j == 3) 
-                           goto Louter; 
-                       if (j == 4) 
-                           goto L2; 
-                   } 
-                 L2: 
-                   ; 
-               } 
-           Louter: 
-               ; 
-
- -

The D Way

- - Break and continue statements can be followed by a label. The label - is the label for an enclosing loop or switch, and the break applies - to that loop. - -
-             Louter: 
-               for (i = 0; i < 10; i++) 
-               { 
-                   for (j = 0; j < 10; j++) 
-                   { 
-                       if (j == 3) 
-                           break Louter; 
-                       if (j == 4) 
-                           continue Louter; 
-                   } 
-               } 
-               // break Louter goes here 
-
- -
- -

Goto Statements

- -

The C Way

- - The much maligned goto statement is a staple for professional C coders. It's - necessary to make up for sometimes inadequate control flow statements. - -

The D Way

- - Many C-way goto statements can be eliminated with the D feature of labelled - break and continue statements. But D is a practical language for practical - programmers who know when the rules need to be broken. So of course D supports - the goto! - -
-

Struct tag name space

- -

The C Way

- - It's annoying to have to put the struct keyword every time a type is specified, - so a common idiom is to use: - -
-               typedef struct ABC { ... } ABC; 
-
- -

The D Way

- - Struct tag names are not in a separate name space, they are in the same name - space as ordinary names. Hence: - -
-               struct ABC { ... }; 
-
- -
- -

Looking up strings

- -

The C Way

- - Given a string, compare the string against a list of possible - values and take action based on which one it is. A typical use - for this might be command line argument processing. - -
-               #include <string.h> 
-               void dostring(char *s) 
-               { 
-                   enum Strings { Hello, Goodbye, Maybe, Max }; 
-                   static char *table[] = { "hello", "goodbye", "maybe" }; 
-                   int i; 
-
-                   for (i = 0; i < Max; i++) 
-                   { 
-                       if (strcmp(s, table[i]) == 0) 
-                           break; 
-                   } 
-                   switch (i) 
-                   { 
-                       case Hello:        ... 
-                       case Goodbye:        ... 
-                       case Maybe:        ... 
-                       default:        ... 
-                   } 
-               } 
-
- - The problem with this is trying to maintain 3 parallel data - structures, the enum, the table, and the switch cases. If there - are a lot of values, the connection between the 3 may not be so - obvious when doing maintenance, and so the situation is ripe for - bugs. - - Additionally, if the number of values becomes large, a binary or - hash lookup will yield a considerable performance increase over - a simple linear search. But coding these can be time consuming, - and they need to be debugged. It's typical that such just never - gets done. - -

The D Way

- - D extends the concept of switch statements to be able to handle - strings as well as numbers. Then, the way to code the string - lookup becomes straightforward: - -
-               void dostring(char[] s) 
-               { 
-                   switch (s) 
-                   { 
-                       case "hello":        ... 
-                       case "goodbye":        ... 
-                       case "maybe":        ... 
-                       default:        ... 
-                   } 
-               } 
-
- - Adding new cases becomes easy. The compiler can be relied on - to generate a fast lookup scheme for it, eliminating the bugs - and time required in hand-coding one. - -
- -

Setting struct member alignment

- -

The C Way

- - It's done through a command line switch which affects the entire - program, and woe results if any modules or libraries didn't get - recompiled. To address this, #pragma's are used: - -
-           #pragma pack(1) 
-           struct ABC 
-           { 
-               ... 
-           }; 
-           #pragma pack() 
-
- - But #pragmas are nonportable both in theory and in practice from - compiler to compiler. - -

The D Way

- - Clearly, since much of the point to setting alignment is for - portability of data, a portable means of expressing it is necessary. - -
-           struct ABC 
-           { 
-               int z;               // z is aligned to the default 
-
-             align (1) int x;       // x is byte aligned 
-             align (4) 
-             { 
-               ...                  // declarations in {} are dword aligned 
-             } 
-             align (2):             // switch to word alignment from here on 
-
-               int y;               // y is word aligned 
-           } 
-
- -
- -

Anonymous Structs and Unions

- -Sometimes, it's nice to control the layout of a struct with nested structs and unions. - -

The C Way

- - C doesn't allow anonymous structs or unions, which means that dummy tag names - and dummy members are necessary: - -
-           struct Foo 
-           {   int i; 
-               union Bar 
-               { 
-                   struct Abc { int x; long y; } _abc; 
-                   char *p; 
-               } _bar; 
-           }; 
-
-           #define x _bar._abc.x 
-           #define y _bar._abc.y 
-           #define p _bar.p 
-
-           struct Foo f; 
-
-           f.i; 
-           f.x; 
-           f.y; 
-           f.p; 
-
- - Not only is it clumsy, but using macros means a symbolic debugger won't understand - what is being done, and the macros have global scope instead of struct scope. - -

The D Way

- - Anonymous structs and unions are used to control the layout in a - more natural manner: - -
-           struct Foo 
-           {   int i; 
-               union 
-               { 
-                   struct { int x; long y; } 
-                   char* p; 
-               } 
-           } 
-
-           Foo f; 
-
-           f.i; 
-           f.x; 
-           f.y; 
-           f.p; 
-
- -
- -

Declaring struct types and variables.

- -

The C Way

- - Is to do it in one statement ending with a semicolon: - -
-           struct Foo { int x; int y; } foo; 
-
- - Or to separate the two: - -
-           struct Foo { int x; int y; };   // note terminating ; 
-           struct Foo foo; 
-
- -

The D Way

- - Struct definitions and declarations can't be done in the same statement: - -
-           struct Foo { int x; int y; }    // note there is no terminating ; 
-           Foo foo; 
-
- - which means that the terminating ; can be dispensed with, eliminating the - confusing difference between struct {} and function & block {} in how semicolons - are used. - -
- -

Getting the offset of a struct member.

- -

The C Way

- - Naturally, another macro is used: - -
-           #include <stddef> 
-           struct Foo { int x; int y; }; 
-
-           off = offsetof(Foo, y); 
-
- -

The D Way

- - An offset is just another property: - -
-           struct Foo { int x; int y; } 
-
-           off = Foo.y.offset; 
-
- -
- -

Union initializations.

- -

The C Way

- - Unions are initialized using the "first member" rule: - -
-           union U { int a; long b; }; 
-           union U x = { 5 };                // initialize member 'a' to 5 
-
- - Adding union members or rearranging them can have disastrous consequences - for any initializers. - -

The D Way

- - In D, which member is being initialized is mentioned explicitly: - -
-           union U { int a; long b; } 
-           U x = { a:5 } 
-
- - avoiding the confusion and maintenance problems. - -
- -

Struct initializations.

- -

The C Way

- - Members are initialized by their position within the {}'s: - -
-           struct S { int a; int b; }; 
-           struct S x = { 5, 3 }; 
-
- - This isn't much of a problem with small structs, but when there - are numerous members, it becomes tedious to get the initializers - carefully lined up with the field declarations. Then, if members are - added or rearranged, all the initializations have to be found and - modified appropriately. This is a minefield for bugs. - -

The D Way

- - Member initialization can be done explicitly: - -
-           struct S { int a; int b; } 
-           S x = { b:3, a:5 } 
-
- - The meaning is clear, and there no longer is a positional dependence. - -
- -

Array initializations.

- -

The C Way

- - C initializes array by positional dependence: -
-           int a[3] = { 3,2,2 }; 
-
- Nested arrays may or may not have the { }: -
-           int b[3][2] = { 2,3, {6,5}, 3,4 }; 
-
-

The D Way

- - D does it by positional dependence too, but an index can be used as well: - The following all produce the same result: -
-    int[3] a = [ 3, 2, 0 ]; 
-    int[3] a = [ 3, 2 ];            // unsupplied initializers are 0, just like in C 
-    int[3] a = [ 2:0, 0:3, 1:2 ]; 
-    int[3] a = [ 2:0, 0:3, 2 ];     // if not supplied, the index is the
-                                    // previous one plus one. 
-
- This can be handy if the array will be indexed by an enum, and the order of - enums may be changed or added to: -
-    enum color { black, red, green }
-    int[3] c = [ black:3, green:2, red:5 ]; 
-
- Nested array initializations must be explicit: -
-    int[2][3] b = [ [2,3], [6,5], [3,4] ]; 
-
-    int[2][3] b = [[2,6,3],[3,5,4]];            // error 
-
- -
- -

Escaped String Literals

- -

The C Way

- - C has problems with the DOS file system because a \ is an escape in a string. To specifiy file c:\root\file.c: -
-    char file[] = "c:\\root\\file.c"; 
-
-This gets even more unpleasant with regular expressions. -Consider the escape sequence to match a quoted string: -
-    /"[^\\]*(\\.[^\\]*)*"/
-
-

In C, this horror is expressed as: -

-    char quoteString[] = "\"[^\\\\]*(\\\\.[^\\\\]*)*\"";
-
-

The D Way

- - Within strings, it is WYSIWYG (what you see is what you get). - Escapes are in separate strings. So: -
-    char[] file = 'c:\root\file.c'; 
-    char[] quoteString = \"  r"[^\\]*(\\.[^\\]*)*"  \";
-
- The famous hello world string becomes: -
-    char[] hello = "hello world" \n; 
-
- -
- -

Ascii vs Wide Characters

- -

Modern programming requires that wchar strings be supported in an easy way, for internationalization of the programs. - -

The C Way

- - C uses the wchar_t and the L prefix on strings: -
-    #include <wchar.h> 
-    char foo_ascii[] = "hello"; 
-    wchar_t foo_wchar[] = L"hello"; 
-
-Things get worse if code is written to be both ascii and wchar compatible. -A macro is used to switch strings from ascii to wchar: -
-    #include <tchar.h> 
-    tchar string[] = TEXT("hello"); 
-
-

The D Way

- -The type of a string is determined by semantic analysis, so there is no need to wrap strings in a macro call: -
-    char[] foo_ascii = "hello";            // string is taken to be ascii 
-    wchar[] foo_wchar = "hello";       // string is taken to be wchar 
-
- -
- -

Arrays that parallel an enum

- -

The C Way

- - Consider: -
-       enum COLORS { red, blue, green, max }; 
-       char *cstring[max] = {"red", "blue", "green" }; 
-
- This is fairly easy to get right because the number of entries is small. But suppose it gets to be fairly large. Then it can get difficult to maintain correctly when new entries are added. - -

The D Way

-
-   enum COLORS { red, blue, green }
-
-    char[][COLORS.max + 1] cstring = 
-    [
-	COLORS.red   : "red",
-	COLORS.blue  : "blue", 
-	COLORS.green : "green",
-    ]; 
-
- -Not perfect, but better. - -
- -

Creating a new typedef'd type

- -

The C Way

- - Typedef's in C are weak, that is, they really do not introduce - a new type. The compiler doesn't distinguish between a typedef - and its underlying type. - -
-	typedef void *Handle;
-	void foo(void *);
-	void bar(Handle);
-
-	Handle h;
-	foo(h);			// coding bug not caught
-	bar(h);			// ok
-	
- - The C solution is to create a dummy struct whose sole - purpose is to get type checking and overloading on the new type. - -
-	struct Handle__ { void *value; }
-	typedef struct Handle__ *Handle;
-	void foo(void *);
-	void bar(Handle);
-
-	Handle h;
-	foo(h);			// syntax error
-	bar(h);			// ok
-	
- - Having a default value for the type involves defining a macro, - a naming convention, and then pedantically following that convention: - -
-	#define HANDLE_INIT ((Handle)-1)
-
-	Handle h = HANDLE_INIT;
-	h = func();
-	if (h != HANDLE_INIT)
-	    ...
-	
- - For the struct solution, things get even more complex: - -
-	struct Handle__ HANDLE_INIT;
-
-	void init_handle()	// call this function upon startup
-	{
-	    HANDLE_INIT.value = (void *)-1;
-	}
-
-	Handle h = HANDLE_INIT;
-	h = func();
-	if (memcmp(&h,&HANDLE_INIT,sizeof(Handle)) != 0)
-	    ...
-	
- - There are 4 names to remember: Handle, HANDLE_INIT, - struct Handle__, value. - -

The D Way

- - No need for idiomatic constructions like the above. Just write: - -
-	typedef void* Handle;
-	void foo(void*);
-	void bar(Handle);
-
-	Handle h;
-	foo(h);
-	bar(h);
-	
- - To handle a default value, add an initializer to the typedef, - and refer to it with the .init property: - -
-	typedef void* Handle = cast(void*)(-1);
-	Handle h;
-	h = func();
-	if (h != Handle.init)
-	    ...
-	
- - There's only one name to remember: Handle. - -
- -

Comparing structs

- -

The C Way

- - While C defines struct assignment in a simple, convenient manner: - -
-	struct A x, y;
-	...
-	x = y;
-	
- - it does not for struct comparisons. Hence, to compare two struct - instances for equality: - -
-	#include <string.h>
-
-	struct A x, y;
-	...
-	if (memcmp(&x, &y, sizeof(struct A)) == 0)
-	    ...
-	
- - Note the obtuseness of this, coupled with the lack of any kind - of help from the language with type checking. -

- - There's a nasty bug lurking in the memcmp(). - The layout of a struct, due to alignment, can have 'holes' in it. - C does not guarantee those holes are assigned any values, and so - two different struct instances can have the same value for each member, - but compare different because the holes contain different garbage. - -

The D Way

- - D does it the obvious, straightforward way: - -
-	A x, y;
-	...
-	if (x == y)
-	    ...
-	
- - -
-

Comparing strings

- -

The C Way

- - The library function strcmp() is used: -
-	char string[] = "hello";
-
-	if (strcmp(string, "betty") == 0)	// do strings match?
-	    ...
-	
- - C uses 0 terminated strings, so the C way has an inherent - inefficiency in constantly scanning for the terminating 0. - -

The D Way

- - Why not use the == operator? - -
-	char[] string = "hello";
-
-	if (string == "betty")
-	    ...
-	
- - D strings have the length stored separately from the string. - Thus, the implementation of string compares can be much faster - than in C (the difference being equivalent to the difference - in speed between the C memcmp() and strcmp()). -

- - D supports comparison operators on strings, too: - -

-	char[] string = "hello";
-
-	if (string < "betty")
-	    ...
-	
- - which is useful for sorting/searching. - -
-

Sorting arrays

- -

The C Way

- - Although many C programmers tend to reimplmement bubble sorts - over and over, the right way to sort in C is to use qsort(): - -
-	int compare(const void *p1, const void *p2)
-	{
-	    type *t1 = (type *)p1;
-	    type *t1 = (type *)p2;
-
-	    return *t1 - *t2;
-	}
-
-	type array[10];
-	...
-	qsort(array, sizeof(array)/sizeof(array[0]),
-		sizeof(array[0]), compare);
-	
- - A compare() must be written for each type, and much careful - typo-prone code needs to be written to make it work. - - -

The D Way

- - Sorting couldn't be easier: - -
-	type[] array;
-	...
-	array.sort;		// sort array in-place
-	
- -
-

Volatile memory access

- -

The C Way

- - To access volatile memory, such as shared memory - or memory mapped I/O, a pointer to volatile is created: -
-	volatile int *p = address;
-
-	i = *p;
-	
- -

The D Way

- - D has volatile as a statement type, not as a type modifier: - -
-	int* p = address;
-
-	volatile { i = *p; }
-	
- -
-

String literals

- -

The C Way

- - String literals in C cannot span multiple lines, so to have - a block of text it is necessary to use \ line splicing: - -
-	"This text spans\n
-	multiple\n
-	lines\n"
-	
- - If there is a lot of text, this can wind up being tedious. - -

The D Way

- - String literals can span multiple lines, as in: - -
-	"This text spans
-	multiple
-	lines
-	"
-	
- - So blocks of text can just be cut and pasted into the D - source. - -
-

Data Structure Traversal

- -

The C Way

- - Consider a function to traverse a recursive data structure. - In this example, there's a simple symbol table of strings. - The data structure is an array of binary trees. - The code needs to do an exhaustive search of it to find - a particular string in it, and determine if it is a unique - instance. -

- - To make this work, a helper function membersearchx - is needed to recursively - walk the trees. The helper function needs to read and write - some context outside of the trees, so a custom struct Paramblock - is created and a pointer to it is used to maximize efficiency. - -

-    struct Symbol
-    {	char *id;
-	struct Symbol *left;
-	struct Symbol *right;
-    };
-
-    struct Paramblock
-    {   char *id;
-	struct Symbol *sm;
-    };
-
-    static void membersearchx(struct Paramblock *p, struct Symbol *s)
-    {
-	while (s)
-	{
-	    if (strcmp(p->id,s->id) == 0)
-	    {
-		if (p->sm)
-		    error("ambiguous member %s\n",p->id);
-		p->sm = s;
-	    }
-
-	    if (s->left)
-		membersearchx(p,s->left);
-	    s = s->right;
-	}
-    }
-
-    struct Symbol *symbol_membersearch(Symbol *table[], int tablemax, char *id)
-    {
-	struct Paramblock pb;
-	int i;
-
-	pb.id = id;
-	pb.sm = NULL;
-	for (i = 0; i < tablemax; i++)
-	{
-	    membersearchx(pb, table[i]);
-	}
-	return pb.sm;
-    }
-    
- -

The D Way

- - This is the same algorithm in D, and it shrinks dramatically. - Since nested functions have access to the lexically enclosing - function's variables, there's no need for a Paramblock or - to deal with its bookkeeping details. The nested helper function - is contained wholly within the function that needs it, - improving locality and maintainability. -

- - The performance of the two versions is indistinguishable. - -

-    class Symbol
-    {	char[] id;
-	Symbol left;
-	Symbol right;
-    }
-
-    Symbol symbol_membersearch(Symbol[] table, char[] id)
-    {   Symbol sm;
-
-	void membersearchx(Symbol s)
-	{
-	    while (s)
-	    {
-		if (id == s.id)
-		{
-		    if (sm)
-			error("ambiguous member %s\n", id);
-		    sm = s;
-		}
-
-		if (s.left)
-		    membersearchx(s.left);
-		s = s.right;
-	    }
-	}
-
-	for (int i = 0; i < table.length; i++)
-	{
-	    membersearchx(table[i]);
-	}
-	return sm;
-    }
-    
- -
-

Unsigned Right Shift

- -

The C Way

- - The right shift operators >> and >>= are signed - shifts if the left operand is a signed integral type, and - are unsigned right shifts if the left operand is an unsigned - integral type. To produce an unsigned right shift on an int, - a cast is necessary: - -
-	int i, j;
-	...
-	j = (unsigned)i >> 3;
-	
- - If i is an int, this works fine. But if i is - of a typedef'd type, - -
-	myint i, j;
-	...
-	j = (unsigned)i >> 3;
-	
- - and myint happens to be a long int, then the cast to - unsigned - will silently throw away the most significant bits, corrupting - the answer. - -

The D Way

- - D has the right shift operators >> and >>= which - behave as they do in C. But D also has explicitly unsigned - right shift operators >>> and >>>= which will - do an unsigned right shift regardless of the sign of the left - operand. Hence, - -
-	myint i, j;
-	...
-	j = i >>> 3;
-	
- - avoids the unsafe cast and will work as expected with any integral - type. - -
-

Dynamic Closures

- -

The C Way

- - Consider a reusable container type. In order to be reusable, - it must support a way to apply arbitrary code to each element - of the container. This is done by creating an apply function - that accepts a function pointer to which is passed each - element of the container contents. -

- - A generic context pointer is also needed, represented here by - void *p. The example here is of a trivial container - class that holds an array of int's, and a user of that container - that computes the maximum of those int's. - -

-	struct Collection
-	{
-	    int array[10];
-
-	    void apply(void *p, void (*fp)(void *, int))
-	    {
-		for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
-		    fp(p, array[i]);
-	    }
-	};
-
-	void comp_max(void *p, int i)
-	{
-	    int *pmax = (int *)p;
-
-	    if (i > *pmax)
-		*pmax = i;
-	}
-
-	void func(Collection *c)
-	{
-	    int max = INT_MIN;
-
-	    c->apply(&max, comp_max);
-	}
-	
- - The C way makes heavy use of pointers and casting. - The casting is tedious, error prone, and loses all type safety. - -

The D Way

- - The D version makes use of delegates to transmit - context information for the apply function, - and nested functions both to capture context - information and to improve locality. - -
	class Collection
-	{
-	    int[10] array;
-
-	    void apply(void delegate(int) fp)
-	    {
-		for (int i = 0; i < array.length; i++)
-		    fp(array[i]);
-	    }
-	}
-
-	void func(Collection c)
-	{
-	    int max = int.min;
-
-	    void comp_max(int i)
-	    {
-		if (i > max)
-		    max = i;
-	    }
-
-	    c.apply(comp_max);
-	}
- - Pointers are eliminated, as well as casting and generic - pointers. The D version is fully type safe. - An alternate method in D makes use of function literals: - -
	void func(Collection c)
-	{
-	    int max = int.min;
-
-	    c.apply(delegate(int i) { if (i > max) max = i; } );
-	}
- - eliminating the need to create irrelevant function names. - -
-

Variadic Function Parameters

- - The task is to write a function that takes a varying - number of arguments, such as a function that sums - its arguments. - -

The C Way

- -
-	#include <stdio.h>
-	#include <stdarg.h>
-
-	int sum(int dim, ...)
-	{   int i;
-	    int s = 0;
-	    va_list ap;
-
-	    va_start(ap, dim);
-	    for (i = 0; i < dim; i++)
-		s += va_arg(ap, int);
-	    va_end(ap);
-	    return s;
-	}
-
-	int main()
-	{
-	    int i;
-
-	    i = sum(3, 8,7,6);
-	    printf("sum = %d\n", i);
-
-	    return 0;
-	} 
-	
- - There are two problems with this. The first is that the - sum function needs to know how many arguments were - supplied. It has to be explicitly written, and it can get - out of sync with respect to the actual number of arguments - written. - The second is that there's no way to check that the - types of the arguments provided really were ints, and not - doubles, strings, structs, etc. - -

The D Way

- - The ... following an array parameter declaration means that - the trailing arguments are collected together to form - an array. The arguments are type checked against the array - type, and the number of arguments becomes a property - of the array: - -
-	int sum(int[] values ...)
-	{
-	    int s = 0;
-
-	    foreach (int x; values)
-		s += x;
-	    return s;
-	}
-
-	int main()
-	{
-	    int i;
-
-	    i = sum(8,7,6);
-	    printf("sum = %d\n", i);
-
-	    return 0;
-	}
-	
- - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +Digital Mars - Programming in D for C Programmers + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:28 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· D vs C/C++/C#/Java
+ + +· Rationale for Builtins
+ + +· Converting C to D
+ + +· Converting C++ to D
+ + +· The C Preprocessor vs D
+ + +· D strings vs C++ std::string
+ + +· D complex vs C++ std::complex
+ + +· D Contract Programming vs C++
+ + +
+
+ +

Programming in D for C Programmers

+ +ouch! + +Every experienced C programmer accumulates a series of idioms and techniques +which become second nature. Sometimes, when learning a new language, those +idioms can be so comfortable it's hard to see how to do the equivalent in the +new language. So here's a collection of common C techniques, and how to do the +corresponding task in D. +

+ +Since C does not have object-oriented features, there's a separate section +for object-oriented issues +Programming in D for C++ Programmers. +

+ +The C preprocessor is covered in +The C Preprocessor vs D. + +

+ +
+

Getting the Size of a Type

+ +

The C Way

+ +
	sizeof(int)
+	sizeof(char *)
+	sizeof(double)
+	sizeof(struct Foo)
+
+ +

The D Way

+ +

Use the size property:

+ +
        int.size
+        (char *).size
+        double.size
+        Foo.size
+
+ +
+ +

Get the max and min values of a type

+ +

The C Way

+ +
	#include <limits.h>
+	#include <math.h>
+
+	CHAR_MAX
+	CHAR_MIN
+	ULONG_MAX
+	DBL_MIN
+
+ + +

The D Way

+ +
        char.max
+        char.min
+        ulong.max
+        double.min
+
+ +
+ +

Primitive Types

+ +

C to D types

+ +
        bool               =>        bit 
+        char               =>        char 
+        signed char        =>        byte 
+        unsigned char      =>        ubyte 
+        short              =>        short 
+        unsigned short     =>        ushort 
+        wchar_t            =>        wchar 
+        int                =>        int 
+        unsigned           =>        uint 
+        long               =>        int 
+        unsigned long      =>        uint 
+        long long          =>        long 
+        unsigned long long =>        ulong 
+        float              =>        float 
+        double             =>        double 
+        long double        =>        real 
+	_Imaginary long double =>    imaginary
+	_Complex long double   =>    complex
+
+
+ +

+ Although char is an unsigned 8 bit type, and + wchar is an unsigned 16 bit type, they have their own separate types + in order to aid overloading and type safety. +

+ Ints and unsigneds in C are of varying size; not so in D. + +


+ +

Special Floating Point Values

+ +

The C Way

+ +
       #include <fp.h> 
+
+       NAN 
+       INFINITY 
+
+       #include <float.h> 
+
+       DBL_DIG 
+       DBL_EPSILON 
+       DBL_MANT_DIG 
+       DBL_MAX_10_EXP 
+       DBL_MAX_EXP 
+       DBL_MIN_10_EXP 
+       DBL_MIN_EXP 
+
+ + +

The D Way

+ +
       double.nan 
+       double.infinity 
+       double.dig 
+       double.epsilon 
+       double.mant_dig 
+       double.max_10_exp 
+       double.max_exp 
+       double.min_10_exp 
+       double.min_exp 
+
+ +
+

Remainder after division of floating point numbers

+ +

The C Way

+ +
+       #include <math.h> 
+
+       float f = fmodf(x,y); 
+       double d = fmod(x,y); 
+       long double r = fmodl(x,y); 
+
+ + +

The D Way

+ +D supports the remainder ('%') operator on floating point operands: + +
       float f = x % y; 
+       double d = x % y; 
+       real r = x % y; 
+
+ +
+ +

Dealing with NAN's in floating point compares

+ +

The C Way

+ + C doesn't define what happens if an operand to a compare + is NAN, and few C compilers check for it (the Digital Mars + C compiler is an exception, DM's compilers do check for NAN operands). + +
+       #include <math.h> 
+
+       if (isnan(x) || isnan(y)) 
+	   result = FALSE; 
+       else 
+	   result = (x < y); 
+
+ + +

The D Way

+

+ D offers a full complement of comparisons and operators + that work with NAN arguments. + +

       result = (x < y);        // false if x or y is nan 
+
+ +
+ +

Assert's are a necessary part of any good defensive coding strategy.

+ +

The C Way

+

+C doesn't directly support assert, but does support __FILE__ +and __LINE__ from which an assert macro can be built. In fact, +there appears to be practically no other use for __FILE__ and __LINE__. + +

+       #include <assert.h> 
+
+       assert(e == 0); 
+
+ + +

The D Way

+ +D simply builds assert into the language: + +
       assert(e == 0); 
+
+ +
+ +

Initializing all elements of an array

+ +

The C Way

+ +
+       #define ARRAY_LENGTH        17 
+       int array[ARRAY_LENGTH]; 
+       for (i = 0; i < ARRAY_LENGTH; i++) 
+	   array[i] = value; 
+
+ + +

The D Way

+ +
       int array[17]; 
+       array[] = value; 
+
+ +
+ +

Looping through an array

+ +

The C Way

+

+ The array length is defined separately, or a clumsy + sizeof() expression is used to get the length. + +

+       #define ARRAY_LENGTH        17 
+       int array[ARRAY_LENGTH]; 
+       for (i = 0; i < ARRAY_LENGTH; i++) 
+	   func(array[i]); 
+
+ + +or: + +
+       int array[17]; 
+       for (i = 0; i < sizeof(array) / sizeof(array[0]); i++) 
+	   func(array[i]); 
+
+ + +

The D Way

+ +The length of an array is accessible the property "length". + +
       int array[17]; 
+       for (i = 0; i &lt; array.length; i++) 
+	   func(array[i]); 
+
+ +or even better: + +
       int array[17]; 
+       foreach (int value; array)
+	   func(value); 
+
+ + +
+ +

Creating an array of variable size

+ +

The C Way

+ + C cannot do this with arrays. It is necessary to create a separate + variable for the length, and then explicitly manage the size of + the array: + +
+       #include <stdlib.h> 
+
+       int array_length; 
+       int *array; 
+       int *newarray; 
+
+       newarray = (int *)
+	   realloc(array, (array_length + 1) * sizeof(int)); 
+       if (!newarray) 
+	   error("out of memory"); 
+       array = newarray; 
+       array[array_length++] = x; 
+
+ + +

The D Way

+ + D supports dynamic arrays, which can be easily resized. D supports + all the requisite memory management. + +
       int[] array; 
+
+       array.length = array.length + 1;
+       array[array.length - 1] = x; 
+
+ +
+ +

String Concatenation

+ +

The C Way

+ + There are several difficulties to be resolved, like + when can storage be free'd, dealing with null pointers, + finding the length of the strings, and memory allocation: + +
 
+       #include <string.h> 
+
+       char *s1; 
+       char *s2; 
+       char *s; 
+
+       // Concatenate s1 and s2, and put result in s 
+       free(s); 
+       s = (char *)malloc((s1 ? strlen(s1) : 0) + 
+			  (s2 ? strlen(s2) : 0) + 1); 
+       if (!s) 
+	   error("out of memory"); 
+       if (s1) 
+	   strcpy(s, s1); 
+       else 
+	   *s = 0; 
+       if (s2) 
+	   strcpy(s + strlen(s), s2); 
+
+       // Append "hello" to s 
+       char hello[] = "hello"; 
+       char *news; 
+       size_t lens = s ? strlen(s) : 0; 
+       news = (char *)
+	   realloc(s, (lens + sizeof(hello) + 1) * sizeof(char)); 
+       if (!news) 
+	   error("out of memory"); 
+       s = news; 
+       memcpy(s + lens, hello, sizeof(hello)); 
+
+ + +

The D Way

+ + D overloads the operators ~ and ~= for char and wchar arrays to mean + concatenate and append, respectively: + +
       char[] s1; 
+       char[] s2; 
+       char[] s; 
+
+       s = s1 ~ s2; 
+       s ~= "hello"; 
+
+ +
+ +

Formatted printing

+ +

The C Way

+ + printf() is the general purpose formatted print routine: + +
+       #include <stdio.h> 
+
+       printf("Calling all cars %d times!\n", ntimes); 
+
+ + +

The D Way

+ + What can we say? printf() rules: + +
       import stdio; 
+
+       printf("Calling all cars %d times!\n", ntimes); 
+
+ +
+ +

Forward referencing functions

+ +

The C Way

+ + Functions cannot be forward referenced. Hence, to call a function + not yet encountered in the source file, it is necessary to insert + a function declaration lexically preceding the call. + +
+       void forwardfunc(); 
+
+       void myfunc() 
+       {   
+	   forwardfunc(); 
+       } 
+
+       void forwardfunc() 
+       {   
+	   ... 
+       } 
+
+ + +

The D Way

+ + The program is looked at as a whole, and so not only is it not + necessary to code forward declarations, it is not even allowed! + D avoids the tedium and errors associated with writing forward + referenced function declarations twice. + Functions can be defined in any order. + +
        void myfunc() 
+        {   
+	   forwardfunc(); 
+        } 
+
+        void forwardfunc() 
+        {   
+	   ... 
+        } 
+
+ +
+ +

Functions that have no arguments

+ +

The C Way

+ +
+       void function(void); 
+
+ + +

The D Way

+ + D is a strongly typed language, so there is no need to explicitly + say a function takes no arguments, just don't declare it has having + arguments. + +
       void function() 
+       {   
+	   ... 
+       } 
+
+ +
+ +

Labelled break's and continue's.

+ +

The C Way

+ + Break's and continue's only apply to the innermost nested loop or + switch, so a multilevel break must use a goto: + +
+       for (i = 0; i < 10; i++) 
+       {   
+	   for (j = 0; j < 10; j++) 
+	   {   
+	       if (j == 3) 
+		   goto Louter; 
+	       if (j == 4) 
+		   goto L2; 
+	   } 
+	 L2: 
+	   ; 
+       } 
+   Louter: 
+       ; 
+
+ + +

The D Way

+ + Break and continue statements can be followed by a label. The label + is the label for an enclosing loop or switch, and the break applies + to that loop. + +
     Louter: 
+       for (i = 0; i < 10; i++) 
+       {   
+	   for (j = 0; j < 10; j++) 
+	   {   
+	       if (j == 3) 
+		   break Louter; 
+	       if (j == 4) 
+		   continue Louter; 
+	   } 
+       } 
+       // break Louter goes here 
+
+ +
+ +

Goto Statements

+ +

The C Way

+ + The much maligned goto statement is a staple for professional C coders. It's + necessary to make up for sometimes inadequate control flow statements. + +

The D Way

+ + Many C-way goto statements can be eliminated with the D feature of labelled + break and continue statements. But D is a practical language for practical + programmers who know when the rules need to be broken. So of course D supports + the goto! + +
+

Struct tag name space

+ +

The C Way

+ + It's annoying to have to put the struct keyword every time a type is specified, + so a common idiom is to use: + +
+       typedef struct ABC { ... } ABC; 
+
+ + +

The D Way

+ + Struct tag names are not in a separate name space, they are in the same name + space as ordinary names. Hence: + +
       struct ABC { ... }; 
+
+ +
+ +

Looking up strings

+ +

The C Way

+ + Given a string, compare the string against a list of possible + values and take action based on which one it is. A typical use + for this might be command line argument processing. + +
+       #include <string.h> 
+       void dostring(char *s) 
+       {   
+	   enum Strings { Hello, Goodbye, Maybe, Max }; 
+	   static char *table[] = { "hello", "goodbye", "maybe" }; 
+	   int i; 
+
+	   for (i = 0; i < Max; i++) 
+	   {   
+	       if (strcmp(s, table[i]) == 0) 
+		   break; 
+	   } 
+	   switch (i) 
+	   {   
+	       case Hello:   ... 
+	       case Goodbye: ... 
+	       case Maybe:   ... 
+	       default:      ... 
+	   } 
+       } 
+
+ + + The problem with this is trying to maintain 3 parallel data + structures, the enum, the table, and the switch cases. If there + are a lot of values, the connection between the 3 may not be so + obvious when doing maintenance, and so the situation is ripe for + bugs. + + Additionally, if the number of values becomes large, a binary or + hash lookup will yield a considerable performance increase over + a simple linear search. But coding these can be time consuming, + and they need to be debugged. It's typical that such just never + gets done. + +

The D Way

+ + D extends the concept of switch statements to be able to handle + strings as well as numbers. Then, the way to code the string + lookup becomes straightforward: + +
       void dostring(char[] s) 
+       {   
+	   switch (s) 
+	   {   
+	       case "hello":   ... 
+	       case "goodbye": ... 
+	       case "maybe":   ... 
+	       default:        ... 
+	   } 
+       } 
+
+ + Adding new cases becomes easy. The compiler can be relied on + to generate a fast lookup scheme for it, eliminating the bugs + and time required in hand-coding one. + +
+ +

Setting struct member alignment

+ +

The C Way

+ + It's done through a command line switch which affects the entire + program, and woe results if any modules or libraries didn't get + recompiled. To address this, #pragma's are used: + +
+           #pragma pack(1) 
+           struct ABC 
+           { 
+               ... 
+           }; 
+           #pragma pack() 
+
+ + + But #pragmas are nonportable both in theory and in practice from + compiler to compiler. + +

The D Way

+ + Clearly, since much of the point to setting alignment is for + portability of data, a portable means of expressing it is necessary. + +
           struct ABC 
+           { 
+               int z;               // z is aligned to the default 
+
+             align (1) int x;       // x is byte aligned 
+             align (4) 
+             { 
+               ...                  // declarations in {} are dword aligned 
+             } 
+             align (2):             // switch to word alignment from here on 
+
+               int y;               // y is word aligned 
+           } 
+
+ +
+ +

Anonymous Structs and Unions

+ +Sometimes, it's nice to control the layout of a struct with nested structs and unions. + +

The C Way

+ + C doesn't allow anonymous structs or unions, which means that dummy tag names + and dummy members are necessary: + +
+       struct Foo 
+       {   int i; 
+	   union Bar 
+	   {   
+	       struct Abc { int x; long y; } _abc; 
+	       char *p; 
+	   } _bar; 
+       }; 
+
+       #define x _bar._abc.x 
+       #define y _bar._abc.y 
+       #define p _bar.p 
+
+       struct Foo f; 
+
+       f.i; 
+       f.x; 
+       f.y; 
+       f.p; 
+
+ + + Not only is it clumsy, but using macros means a symbolic debugger won't understand + what is being done, and the macros have global scope instead of struct scope. + +

The D Way

+ + Anonymous structs and unions are used to control the layout in a + more natural manner: + +
       struct Foo 
+       {   int i; 
+	   union 
+	   {   
+	       struct { int x; long y; } 
+	       char* p; 
+	   } 
+       } 
+
+       Foo f; 
+
+       f.i; 
+       f.x; 
+       f.y; 
+       f.p; 
+
+ +
+ +

Declaring struct types and variables.

+ +

The C Way

+ + Is to do it in one statement ending with a semicolon: + +
+           struct Foo { int x; int y; } foo; 
+
+ + + Or to separate the two: + +
+           struct Foo { int x; int y; };   // note terminating ; 
+           struct Foo foo; 
+
+ + +

The D Way

+ + Struct definitions and declarations can't be done in the same statement: + +
       struct Foo { int x; int y; }    // note there is no terminating ; 
+       Foo foo; 
+
+ + which means that the terminating ; can be dispensed with, eliminating the + confusing difference between struct {} and function & block {} in how semicolons + are used. + +
+ +

Getting the offset of a struct member.

+ +

The C Way

+ + Naturally, another macro is used: + +
+       #include <stddef> 
+       struct Foo { int x; int y; }; 
+
+       off = offsetof(Foo, y); 
+
+ + +

The D Way

+ + An offset is just another property: + +
       struct Foo { int x; int y; } 
+
+       off = Foo.y.offset; 
+
+ +
+ +

Union initializations.

+ +

The C Way

+ + Unions are initialized using the "first member" rule: + +
+       union U { int a; long b; }; 
+       union U x = { 5 };                // initialize member 'a' to 5 
+
+ + + Adding union members or rearranging them can have disastrous consequences + for any initializers. + +

The D Way

+ + In D, which member is being initialized is mentioned explicitly: + +
       union U { int a; long b; } 
+       U x = { a:5 } 
+
+ + avoiding the confusion and maintenance problems. + +
+ +

Struct initializations.

+ +

The C Way

+ + Members are initialized by their position within the {}'s: + +
+       struct S { int a; int b; }; 
+       struct S x = { 5, 3 }; 
+
+ + + This isn't much of a problem with small structs, but when there + are numerous members, it becomes tedious to get the initializers + carefully lined up with the field declarations. Then, if members are + added or rearranged, all the initializations have to be found and + modified appropriately. This is a minefield for bugs. + +

The D Way

+ + Member initialization can be done explicitly: + +
       struct S { int a; int b; } 
+       S x = { b:3, a:5 } 
+
+ + The meaning is clear, and there no longer is a positional dependence. + +
+ +

Array initializations.

+ +

The C Way

+ + C initializes array by positional dependence: +
+           int a[3] = { 3,2,2 }; 
+
+ + Nested arrays may or may not have the { }: +
+           int b[3][2] = { 2,3, {6,5}, 3,4 }; 
+
+ + +

The D Way

+ + D does it by positional dependence too, but an index can be used as well: + The following all produce the same result: + +
    int[3] a = [ 3, 2, 0 ]; 
+    int[3] a = [ 3, 2 ];            // unsupplied initializers are 0, just like in C 
+    int[3] a = [ 2:0, 0:3, 1:2 ]; 
+    int[3] a = [ 2:0, 0:3, 2 ];     // if not supplied, the index is the
+                                    // previous one plus one. 
+
+ This can be handy if the array will be indexed by an enum, and the order of + enums may be changed or added to: + +
    enum color { black, red, green }
+    int[3] c = [ black:3, green:2, red:5 ]; 
+
+ Nested array initializations must be explicit: +
    int[2][3] b = [ [2,3], [6,5], [3,4] ]; 
+
+    int[2][3] b = [[2,6,3],[3,5,4]];            // error 
+
+ +
+ +

Escaped String Literals

+ +

The C Way

+ + C has problems with the DOS file system because a \ is an escape in a string. To specifiy file c:\root\file.c: +
+    char file[] = "c:\\root\\file.c"; 
+
+ +This gets even more unpleasant with regular expressions. +Consider the escape sequence to match a quoted string: +
+    /"[^\\]*(\\.[^\\]*)*"/
+
+ +

In C, this horror is expressed as: +

+    char quoteString[] = "\"[^\\\\]*(\\\\.[^\\\\]*)*\"";
+
+ +

The D Way

+ + Within strings, it is WYSIWYG (what you see is what you get). + Escapes are in separate strings. So: + +
    char[] file = `c:\root\file.c`; 
+    char[] quoteString = \"  r"[^\\]*(\\.[^\\]*)*"  \";
+
+ + The famous hello world string becomes: +
    char[] hello = "hello world" \n; 
+
+ +
+ +

Ascii vs Wide Characters

+ +

Modern programming requires that wchar strings be supported in an easy way, for internationalization of the programs. + +

The C Way

+ + C uses the wchar_t and the L prefix on strings: +
+    #include <wchar.h> 
+    char foo_ascii[] = "hello"; 
+    wchar_t foo_wchar[] = L"hello"; 
+
+ +Things get worse if code is written to be both ascii and wchar compatible. +A macro is used to switch strings from ascii to wchar: +
+    #include <tchar.h> 
+    tchar string[] = TEXT("hello"); 
+
+ +

The D Way

+ +The type of a string is determined by semantic analysis, so there is no need to wrap strings in a macro call: +
    char[] foo_ascii = "hello";            // string is taken to be ascii 
+    wchar[] foo_wchar = "hello";       // string is taken to be wchar 
+
+ +
+ +

Arrays that parallel an enum

+ +

The C Way

+ + Consider: +
+       enum COLORS { red, blue, green, max }; 
+       char *cstring[max] = {"red", "blue", "green" }; 
+
+ + This is fairly easy to get right because the number of entries is small. But suppose it gets to be fairly large. Then it can get difficult to maintain correctly when new entries are added. + +

The D Way

+
   enum COLORS { red, blue, green }
+
+    char[][COLORS.max + 1] cstring = 
+    [
+	COLORS.red   : "red",
+	COLORS.blue  : "blue", 
+	COLORS.green : "green",
+    ]; 
+
+ +Not perfect, but better. + +
+ +

Creating a new typedef'd type

+ +

The C Way

+ + Typedef's in C are weak, that is, they really do not introduce + a new type. The compiler doesn't distinguish between a typedef + and its underlying type. + +
+	typedef void *Handle;
+	void foo(void *);
+	void bar(Handle);
+
+	Handle h;
+	foo(h);			// coding bug not caught
+	bar(h);			// ok
+	
+ + + The C solution is to create a dummy struct whose sole + purpose is to get type checking and overloading on the new type. + +
+	struct Handle__ { void *value; }
+	typedef struct Handle__ *Handle;
+	void foo(void *);
+	void bar(Handle);
+
+	Handle h;
+	foo(h);			// syntax error
+	bar(h);			// ok
+	
+ + + Having a default value for the type involves defining a macro, + a naming convention, and then pedantically following that convention: + +
+	#define HANDLE_INIT ((Handle)-1)
+
+	Handle h = HANDLE_INIT;
+	h = func();
+	if (h != HANDLE_INIT)
+	    ...
+	
+ + + For the struct solution, things get even more complex: + +
+	struct Handle__ HANDLE_INIT;
+
+	void init_handle()	// call this function upon startup
+	{
+	    HANDLE_INIT.value = (void *)-1;
+	}
+
+	Handle h = HANDLE_INIT;
+	h = func();
+	if (memcmp(&h,&HANDLE_INIT,sizeof(Handle)) != 0)
+	    ...
+	
+ + + There are 4 names to remember: Handle, HANDLE_INIT, + struct Handle__, value. + +

The D Way

+ + No need for idiomatic constructions like the above. Just write: + +
	typedef void* Handle;
+	void foo(void*);
+	void bar(Handle);
+
+	Handle h;
+	foo(h);
+	bar(h);
+
+ + To handle a default value, add an initializer to the typedef, + and refer to it with the .init property: + +
	typedef void* Handle = cast(void*)(-1);
+	Handle h;
+	h = func();
+	if (h != Handle.init)
+	    ...
+
+ + There's only one name to remember: Handle. + +
+ +

Comparing structs

+ +

The C Way

+ + While C defines struct assignment in a simple, convenient manner: + +
+	struct A x, y;
+	...
+	x = y;
+	
+ + + it does not for struct comparisons. Hence, to compare two struct + instances for equality: + +
+	#include <string.h>
+
+	struct A x, y;
+	...
+	if (memcmp(&x, &y, sizeof(struct A)) == 0)
+	    ...
+	
+ + + Note the obtuseness of this, coupled with the lack of any kind + of help from the language with type checking. +

+ + There's a nasty bug lurking in the memcmp(). + The layout of a struct, due to alignment, can have 'holes' in it. + C does not guarantee those holes are assigned any values, and so + two different struct instances can have the same value for each member, + but compare different because the holes contain different garbage. + +

The D Way

+ + D does it the obvious, straightforward way: + +
	A x, y;
+	...
+	if (x == y)
+	    ...
+
+ + +
+

Comparing strings

+ +

The C Way

+ + The library function strcmp() is used: +
+	char string[] = "hello";
+
+	if (strcmp(string, "betty") == 0)	// do strings match?
+	    ...
+	
+ + + C uses 0 terminated strings, so the C way has an inherent + inefficiency in constantly scanning for the terminating 0. + +

The D Way

+ + Why not use the == operator? + +
	char[] string = "hello";
+
+	if (string == "betty")
+	    ...
+
+ + D strings have the length stored separately from the string. + Thus, the implementation of string compares can be much faster + than in C (the difference being equivalent to the difference + in speed between the C memcmp() and strcmp()). +

+ + D supports comparison operators on strings, too: + +

	char[] string = "hello";
+
+	if (string < "betty")
+	    ...
+
+ + which is useful for sorting/searching. + +
+

Sorting arrays

+ +

The C Way

+ + Although many C programmers tend to reimplmement bubble sorts + over and over, the right way to sort in C is to use qsort(): + +
+	int compare(const void *p1, const void *p2)
+	{
+	    type *t1 = (type *)p1;
+	    type *t1 = (type *)p2;
+
+	    return *t1 - *t2;
+	}
+
+	type array[10];
+	...
+	qsort(array, sizeof(array)/sizeof(array[0]),
+		sizeof(array[0]), compare);
+	
+ + + A compare() must be written for each type, and much careful + typo-prone code needs to be written to make it work. + + +

The D Way

+ + Sorting couldn't be easier: + +
	type[] array;
+	...
+	array.sort;		// sort array in-place
+
+ +
+

Volatile memory access

+ +

The C Way

+ + To access volatile memory, such as shared memory + or memory mapped I/O, a pointer to volatile is created: +
+	volatile int *p = address;
+
+	i = *p;
+	
+ + +

The D Way

+ + D has volatile as a statement type, not as a type modifier: + +
	int* p = address;
+
+	volatile { i = *p; }
+
+ +
+

String literals

+ +

The C Way

+ + String literals in C cannot span multiple lines, so to have + a block of text it is necessary to use \ line splicing: + +
+	"This text spans\n\
+	multiple\n\
+	lines\n"
+	
+ + + If there is a lot of text, this can wind up being tedious. + +

The D Way

+ + String literals can span multiple lines, as in: + +
	"This text spans
+	multiple
+	lines
+	"
+
+ + So blocks of text can just be cut and pasted into the D + source. + +
+

Data Structure Traversal

+ +

The C Way

+ + Consider a function to traverse a recursive data structure. + In this example, there's a simple symbol table of strings. + The data structure is an array of binary trees. + The code needs to do an exhaustive search of it to find + a particular string in it, and determine if it is a unique + instance. +

+ + To make this work, a helper function membersearchx + is needed to recursively + walk the trees. The helper function needs to read and write + some context outside of the trees, so a custom struct Paramblock + is created and a pointer to it is used to maximize efficiency. + +

+    struct Symbol
+    {	char *id;
+	struct Symbol *left;
+	struct Symbol *right;
+    };
+
+    struct Paramblock
+    {   char *id;
+	struct Symbol *sm;
+    };
+
+    static void membersearchx(struct Paramblock *p, struct Symbol *s)
+    {
+	while (s)
+	{
+	    if (strcmp(p->id,s->id) == 0)
+	    {
+		if (p->sm)
+		    error("ambiguous member %s\n",p->id);
+		p->sm = s;
+	    }
+
+	    if (s->left)
+		membersearchx(p,s->left);
+	    s = s->right;
+	}
+    }
+
+    struct Symbol *symbol_membersearch(Symbol *table[], int tablemax, char *id)
+    {
+	struct Paramblock pb;
+	int i;
+
+	pb.id = id;
+	pb.sm = NULL;
+	for (i = 0; i < tablemax; i++)
+	{
+	    membersearchx(pb, table[i]);
+	}
+	return pb.sm;
+    }
+    
+ + +

The D Way

+ + This is the same algorithm in D, and it shrinks dramatically. + Since nested functions have access to the lexically enclosing + function's variables, there's no need for a Paramblock or + to deal with its bookkeeping details. The nested helper function + is contained wholly within the function that needs it, + improving locality and maintainability. +

+ + The performance of the two versions is indistinguishable. + +

    class Symbol
+    {	char[] id;
+	Symbol left;
+	Symbol right;
+    }
+
+    Symbol symbol_membersearch(Symbol[] table, char[] id)
+    {   Symbol sm;
+
+	void membersearchx(Symbol s)
+	{
+	    while (s)
+	    {
+		if (id == s.id)
+		{
+		    if (sm)
+			error("ambiguous member %s\n", id);
+		    sm = s;
+		}
+
+		if (s.left)
+		    membersearchx(s.left);
+		s = s.right;
+	    }
+	}
+
+	for (int i = 0; i < table.length; i++)
+	{
+	    membersearchx(table[i]);
+	}
+	return sm;
+    }
+
+ +
+

Unsigned Right Shift

+ +

The C Way

+ + The right shift operators >> and >>= are signed + shifts if the left operand is a signed integral type, and + are unsigned right shifts if the left operand is an unsigned + integral type. To produce an unsigned right shift on an int, + a cast is necessary: + +
+	int i, j;
+	...
+	j = (unsigned)i >> 3;
+	
+ + + If i is an int, this works fine. But if i is + of a typedef'd type, + +
+	myint i, j;
+	...
+	j = (unsigned)i >> 3;
+	
+ + + and myint happens to be a long int, then the cast to + unsigned + will silently throw away the most significant bits, corrupting + the answer. + +

The D Way

+ + D has the right shift operators >> and >>= which + behave as they do in C. But D also has explicitly unsigned + right shift operators >>> and >>>= which will + do an unsigned right shift regardless of the sign of the left + operand. Hence, + +
	myint i, j;
+	...
+	j = i >>> 3;
+
+ + avoids the unsafe cast and will work as expected with any integral + type. + +
+

Dynamic Closures

+ +

The C Way

+ + Consider a reusable container type. In order to be reusable, + it must support a way to apply arbitrary code to each element + of the container. This is done by creating an apply function + that accepts a function pointer to which is passed each + element of the container contents. +

+ + A generic context pointer is also needed, represented here by + void *p. The example here is of a trivial container + class that holds an array of int's, and a user of that container + that computes the maximum of those int's. + +

+	struct Collection
+	{
+	    int array[10];
+
+	    void apply(void *p, void (*fp)(void *, int))
+	    {
+		for (int i = 0; i < sizeof(array)/sizeof(array[0]); i++)
+		    fp(p, array[i]);
+	    }
+	};
+
+	void comp_max(void *p, int i)
+	{
+	    int *pmax = (int *)p;
+
+	    if (i > *pmax)
+		*pmax = i;
+	}
+
+	void func(Collection *c)
+	{
+	    int max = INT_MIN;
+
+	    c->apply(&max, comp_max);
+	}
+	
+ + + The C way makes heavy use of pointers and casting. + The casting is tedious, error prone, and loses all type safety. + +

The D Way

+ + The D version makes use of delegates to transmit + context information for the apply function, + and nested functions both to capture context + information and to improve locality. + +
	class Collection
+	{
+	    int[10] array;
+
+	    void apply(void delegate(int) fp)
+	    {
+		for (int i = 0; i < array.length; i++)
+		    fp(array[i]);
+	    }
+	}
+
+	void func(Collection c)
+	{
+	    int max = int.min;
+
+	    void comp_max(int i)
+	    {
+		if (i > max)
+		    max = i;
+	    }
+
+	    c.apply(comp_max);
+	}
+
+ + Pointers are eliminated, as well as casting and generic + pointers. The D version is fully type safe. + An alternate method in D makes use of function literals: + +
	void func(Collection c)
+	{
+	    int max = int.min;
+
+	    c.apply(delegate(int i) { if (i > max) max = i; } );
+	}
+
+ + eliminating the need to create irrelevant function names. + +
+

Variadic Function Parameters

+ + The task is to write a function that takes a varying + number of arguments, such as a function that sums + its arguments. + +

The C Way

+ +
+	#include <stdio.h>
+	#include <stdarg.h>
+
+	int sum(int dim, ...)
+	{   int i;
+	    int s = 0;
+	    va_list ap;
+
+	    va_start(ap, dim);
+	    for (i = 0; i < dim; i++)
+		s += va_arg(ap, int);
+	    va_end(ap);
+	    return s;
+	}
+
+	int main()
+	{
+	    int i;
+
+	    i = sum(3, 8,7,6);
+	    printf("sum = %d\n", i);
+
+	    return 0;
+	} 
+	
+ + + There are two problems with this. The first is that the + sum function needs to know how many arguments were + supplied. It has to be explicitly written, and it can get + out of sync with respect to the actual number of arguments + written. + The second is that there's no way to check that the + types of the arguments provided really were ints, and not + doubles, strings, structs, etc. + +

The D Way

+ + The ... following an array parameter declaration means that + the trailing arguments are collected together to form + an array. The arguments are type checked against the array + type, and the number of arguments becomes a property + of the array: + +
	int sum(int[] values ...)
+	{
+	    int s = 0;
+
+	    foreach (int x; values)
+		s += x;
+	    return s;
+	}
+
+	int main()
+	{
+	    int i;
+
+	    i = sum(8,7,6);
+	    printf("sum = %d\n", i);
+
+	    return 0;
+	}
+
+ +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/dbc.html dmd-0.136/dmd/html/d/dbc.html --- dmd-0.135/dmd/html/d/dbc.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/dbc.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,330 +1,377 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Contract Programming - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

Contract Programming

- - Contracts are a breakthrough technique to reduce the programming effort - for large projects. Contracts are the concept of preconditions, postconditions, - errors, and invariants. - Contracts can be done in C++ without modification to the language, - but the result is - clumsy and inconsistent. -

- - Building contract support into the language makes for: - -

    -
  1. a consistent look and feel for the contracts -
  2. tool support -
  3. it's possible the compiler can generate better code using information gathered - from the contracts -
  4. easier management and enforcement of contracts -
  5. handling of contract inheritance -
- -Contracts make D bug resistant - - The idea of a contract is simple - it's just an expression that must evaluate to true. - If it does not, the contract is broken, and by definition, the program has a bug in it. - Contracts form part of the specification for a program, moving it from the documentation - to the code itself. And as every programmer knows, documentation tends to be incomplete, - out of date, wrong, or non-existent. Moving the contracts into the code makes them - verifiable against the program. - -

Assert Contract

- - The most basic contract is the - assert. - An assert inserts a checkable expression into - the code, and that expression must evaluate to true: -
-	assert(expression);
-
- C programmers will find it familiar. Unlike C, however, an assert - in function bodies - works by throwing an AssertException, - which can be caught and handled. Catching the contract violation is useful - when the code must deal with errant uses by other code, when it must be - failure proof, and as a useful tool for debugging. - -

Pre and Post Contracts

- - The pre contracts specify the preconditions before a statement is executed. The most - typical use of this would be in validating the parameters to a function. The post - contracts validate the result of the statement. The most typical use of this - would be in validating the return value of a function and of any side effects it has. - The syntax is: - -
-	in
-	{
-	    ...contract preconditions...
-	}
-	out (result)
-	{
-	    ...contract postconditions...
-	}
-	body
-	{
-	    ...code...
-	}
-
- By definition, if a pre contract fails, then the body received bad parameters. - An InException is thrown. If a post contract fails, - then there is a bug in the body. An OutException is thrown. -

- Either the in or the out clause can be omitted. - If the out clause is for a function - body, the variable result is declared and assigned the return - value of the function. - For example, let's implement a square root function: -

-	long square_root(long x)
-	    in
-	    {
-		assert(x >= 0);
-	    }
-	    out (result)
-	    {
-		assert((result * result) == x);
-	    }
-	    body
-	    {
-		return math.sqrt(x);
-	    }
-
- The assert's in the in and out bodies are called contracts. - Any other D - statement or expression is allowed in the bodies, but it is important - to ensure that the - code has no side effects, and that the release version of the code - will not depend on any effects of the code. - For a release build of the code, the in and out code is not - inserted. -

- If the function returns a void, there is no result, and so there can be no - result declaration in the out clause. - In that case, use: -

-	void func()
-	   out
-	   {
-		...contracts...
-	   }
-	   body
-	   {
-		...
-	   }
-
- In an out statement, result is initialized and set to the - return value of the function. -

- The compiler can be adjusted to verify that every in and inout parameter is referenced - in the in { }, - and every out and inout parameter is referenced in the out { }. -

- The in-out statement can also be used inside a function, for example, it can be used - to check the results of a loop: -

-	in
-	{
-	    assert(j == 0);
-	}
-	out
-	{
-	    assert(j == 10);
-	}
-	body
-	{
-	    for (i = 0; i < 10; i++)
-		j++;
-	}
-
- This is not implemented at this time. - -

In, Out and Inheritance

- - If a function in a derived class overrides a function in its - super class, then only one of - the in contracts of the base functions must be satisified - Overriding - functions then becomes a process of loosening the in - contracts. -

- Conversely, all of the out contracts needs to be satisified, so - overriding functions becomes a processes of tightening the out - contracts. - - - -

Class Invariants

- - Class invariants are used to specify characteristics of a class that always - must be true (except while executing a member function). - They are described in Classes. - - -

References

-Contracts Reading List
-Adding Contracts to Java
- -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Contract Programming + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

Contract Programming

+ + Contracts are a breakthrough technique to reduce the programming effort + for large projects. Contracts are the concept of preconditions, postconditions, + errors, and invariants. + Contracts can be done in C++ without modification to the language, + but the result is + clumsy and inconsistent. +

+ + Building contract support into the language makes for: + +

    +
  1. a consistent look and feel for the contracts +
  2. tool support +
  3. it's possible the compiler can generate better code using information gathered + from the contracts +
  4. easier management and enforcement of contracts +
  5. handling of contract inheritance +
+ +Contracts make D bug resistant + + The idea of a contract is simple - it's just an expression that must evaluate to true. + If it does not, the contract is broken, and by definition, the program has a bug in it. + Contracts form part of the specification for a program, moving it from the documentation + to the code itself. And as every programmer knows, documentation tends to be incomplete, + out of date, wrong, or non-existent. Moving the contracts into the code makes them + verifiable against the program. + +

Assert Contract

+ + The most basic contract is the + assert. + An assert inserts a checkable expression into + the code, and that expression must evaluate to true: +
assert(expression);
+
+ C programmers will find it familiar. Unlike C, however, an assert + in function bodies + works by throwing an AssertException, + which can be caught and handled. Catching the contract violation is useful + when the code must deal with errant uses by other code, when it must be + failure proof, and as a useful tool for debugging. + +

Pre and Post Contracts

+ + The pre contracts specify the preconditions before a statement is executed. The most + typical use of this would be in validating the parameters to a function. The post + contracts validate the result of the statement. The most typical use of this + would be in validating the return value of a function and of any side effects it has. + The syntax is: + +
in
+{
+    ...contract preconditions...
+}
+out (result)
+{
+    ...contract postconditions...
+}
+body
+{
+    ...code...
+}
+
+ By definition, if a pre contract fails, then the body received bad parameters. + An InException is thrown. If a post contract fails, + then there is a bug in the body. An OutException is thrown. +

+ Either the in or the out clause can be omitted. + If the out clause is for a function + body, the variable result is declared and assigned the return + value of the function. + For example, let's implement a square root function: +

long square_root(long x)
+    in
+    {
+	assert(x >= 0);
+    }
+    out (result)
+    {
+	assert((result * result) == x);
+    }
+    body
+    {
+	return math.sqrt(x);
+    }
+
+ The assert's in the in and out bodies are called contracts. + Any other D + statement or expression is allowed in the bodies, but it is important + to ensure that the + code has no side effects, and that the release version of the code + will not depend on any effects of the code. + For a release build of the code, the in and out code is not + inserted. +

+ If the function returns a void, there is no result, and so there can be no + result declaration in the out clause. + In that case, use: +

void func()
+   out
+   {
+	...contracts...
+   }
+   body
+   {
+	...
+   }
+
+ In an out statement, result is initialized and set to the + return value of the function. +

+ The compiler can be adjusted to verify that every in and inout parameter is referenced + in the in { }, + and every out and inout parameter is referenced in the out { }. +

+ The in-out statement can also be used inside a function, for example, it can be used + to check the results of a loop: +

in
+{
+    assert(j == 0);
+}
+out
+{
+    assert(j == 10);
+}
+body
+{
+    for (i = 0; i < 10; i++)
+	j++;
+}
+
+ This is not implemented at this time. + +

In, Out and Inheritance

+ + If a function in a derived class overrides a function in its + super class, then only one of + the in contracts of the base functions must be satisified + Overriding + functions then becomes a process of loosening the in + contracts. +

+ Conversely, all of the out contracts needs to be satisified, so + overriding functions becomes a processes of tightening the out + contracts. + + + +

Class Invariants

+ + Class invariants are used to specify characteristics of a class that always + must be true (except while executing a member function). + They are described in Classes. + + +

References

+ +Contracts Reading List
+Adding Contracts to Java
+ + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/dcompiler.html dmd-0.136/dmd/html/d/dcompiler.html --- dmd-0.135/dmd/html/d/dcompiler.html 2005-09-24 12:56:42.000000000 +0200 +++ dmd-0.136/dmd/html/d/dcompiler.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,681 +1,728 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - DMD Compiler - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sat Sep 24 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - - -

Compiler for D Programming Language

- - - -

Files Common to Win32 and Linux

- -
- -
\dmd\src\phobos\ -
D runtime library source - -
\dmd\src\dmd\ -
D compiler front end source under dual (GPL and Artistic) license - -
\dmd\html\d\ -
Documentation - -
\dmd\samples\d\ -
Sample D programs - -
- -
-

Win32 D Compiler

- -

Files

- -
- -
\dmd\bin\dmd.exe -
D compiler executable - -
\dmd\bin\shell.exe -
Simple command line shell - -
\dmd\bin\sc.ini -
Global compiler settings - -
\dmd\lib\phobos.lib -
D runtime library - -
- -

Requirements

- - - -

Installation

- - Open a console window (for Windows XP this is done by - clicking on [Start][Command Prompt]). - All the tools are command line tools, which means - they are run from a console window. - Switch to the root directory. - Unzip the files in the root directory. - dmd.zip will create - a \dmd directory with all the files in it. - dmc.zip will create - a \dm directory with all the files in it. -

- - A typical session might look like: - -

-	C:\Documents and Settings\Your Name>cd 
-	C:\>unzip dmd.zip
-	C:\>unzip dmc.zip
-	
- -

Example

- - Run: -
-	\dmd\bin\shell all.sh
-	
- in the \dmd\samples\d directory for several small examples. - -

Compiler Arguments and Switches

- -
-
dmd files... -switch... -

-

files... -
- - - - - - - - -
Extension - File Type -
none - D source files -
.d - D source files -
.obj - Object files to link in -
.exe - Name output executable file -
.def - module definition file -
.res - resource file -
- -
-c
-
compile only, do not link
- -
-D
-
generate documentation
- -
-Dddocdir
-
write documentation file to docdir directory
- -
-Dffilename
-
write documentation file to filename
- -
-d
-
allow deprecated features -
-debug
-
compile in debug code -
-debug=level
-
compile in debug code <= level -
-debug=ident
-
compile in debug code identified by ident -
-g
-
add symbolic debug info -
-inline -
inline expand functions -
-Ipath -
where to look for imports. path is a ; separated - list of paths. Multiple -I's can be used, and the paths - are searched in the same order. -
-Llinkerflag -
pass linkerflag to the linker, for example, - /ma/li -
-O
-
optimize -
-o-
-
suppress generation of object file -
-odobjdir
-
write object files relative to directory objdir - instead of to the current directory -
-offilename
-
set output file name to filename in the output - directory -
-op
-
normally the path for .d source files is stripped - off when generating an object file name. -op will leave - it on. -
-profile
-
profile - the runtime performance - of the generated code -
-quiet
-
suppress non-essential compiler messages -
-release
-
compile release version, which means not generating - code for contracts and asserts -
-unittest
-
compile in unittest code, also turns on asserts -
-v
-
verbose -
-version=level
-
compile in version code >= level -
-version=ident
-
compile in version code identified by ident -
-w
-
enable warnings -
- -

Linking

- - Linking is done directly by the dmd compiler after a successful - compile. To prevent dmd from running the linker, use the - -c switch. -

- - The programs must be linked with the D runtime library phobos.lib, - followed by the C runtime library snn.lib. - This is done automatically as long as the directories for the - libraries are on the LIB environment variable path. A typical - way to set LIB would be: -

-	set LIB=\dmd\lib;\dm\lib
-	
- -

Environment Variables

- - The D compiler dmd uses the following environment variables: - -
- -
DFLAGS -
The value of DFLAGS is treated as if it were appended to the - command line to dmd.exe. - -
LIB -
The linker uses LIB to search for library files. For D, it will - normally be set to: -
-	set LIB=\dmd\lib;\dm\lib
- -
LINKCMD -
dmd normally runs the linker by looking for link.exe - along the PATH. To use a specific linker instead, set the - LINKCMD environment variable to it. For example: -
-	set LINKCMD=\dm\bin\link
- -
PATH -
If the linker is not found in the same directory as dmd.exe - is in, the PATH is searched for it. - Note: other linkers named - link.exe will likely not work. - Make sure the Digital Mars link.exe - is found first in the PATH before other link.exe's, - or use LINKCMD to specifically identify which linker - to use. - -
- -

SC.INI Initialization File

- - dmd will look for the initialization file sc.ini in the same - directory dmd.exe resides in. If found, environment variable - settings in the file will override any existing settings. - This is handy to make dmd independent of programs with - conflicting use of environment variables. -

- - Environment variables follow the [Environment] section - heading, in name=value pairs. Comments are lines that start with ;. - For example: -

-	; sc.ini file for dmd
-	; Names enclosed by %% are searched for in the existing environment
-	; and inserted. The special name %@P% is replaced with the path
-	; to this file.
-	[Environment]
-	LIB="%@P%\..\lib";\dm\lib
-	DFLAGS="-I%@P%\..\src\phobos"
-	LINKCMD="%@P%\..\..\dm\bin"
-	DDOCFILE=mysettings.ddoc
-	
- -

Common Installation Problems

- -
    -
  • Using Cygwin's unzip utility has been known to cause - strange problems. -
  • Running the compiler under Cygwin's command shell has - been also known to cause problems. Try getting it to work - under the regular Windows shell cmd.exe before trying Cygwin's. -
  • Installing dmd and dmc into directory paths with spaces - in them causes problems. -
- -
-

Linux D Compiler

- -

Files

- -
- -
/dmd/bin/dmd -
D compiler executable - -
/dmd/bin/dumpobj -
Elf file dumper - -
/dmd/bin/obj2asm -
Elf file disassembler - -
/dmd/bin/dmd.conf -
Global compiler settings (copy to /etc/dmd.conf) - -
/dmd/lib/libphobos.a -
D runtime library (copy to /usr/lib/libphobos.a) - -
- -

Requirements

- -
    -
  • 32 bit x86 Linux operating system - -
  • - - D compiler for Linux - -
  • Gnu C compiler (gcc) - -
- -

Installation

- -
    - -
  1. Unzip the archive into your home directory. - It will create - a ~/dmd directory with all the files in it. - All the tools are command line tools, which means - they are run from a console window. - -
  2. Edit the file ~/dmd/bin/dmd.conf to put the path in to - where the phobos source files are. - -
  3. Copy dmd.conf to /etc: - -
    -	cp dmd/bin/dmd.conf /etc
    -	
    - -
  4. Give execute permission to the following files: - -
    -	chmod u+x dmd/bin/dmd dmd/bin/obj2asm dmd/bin/dumpobj
    -	
    - -
  5. Put dmd/bin on your PATH, - or copy the linux executables - to /usr/local/bin - -
  6. Copy the library to /usr/lib: - -
    -	cp dmd/lib/libphobos.a /usr/lib
    -	
    - -
- -

Compiler Arguments and Switches

- -
-
dmd files... -switch... -

-

files... -
- - - - - - - -
Extension - File Type -
none - D source files -
.d - D source files -
.o - Object files to link in -
.a - Library files to link in -
- -
-c
-
compile only, do not link
- -
-D
-
generate documentation
- -
-Dddocdir
-
write documentation file to docdir directory
- -
-Dffilename
-
write documentation file to filename
- -
-d
-
allow deprecated features -
-debug
-
compile in debug code -
-debug=level
-
compile in debug code <= level -
-debug=ident
-
compile in debug code identified by ident -
-g
-
add symbolic debug info -
-gc
-
add symbolic debug info in C format (for older gdb's) -
-inline -
inline expand functions -
-Ipath -
where to look for imports. path is a ; separated - list of paths. Multiple -I's can be used, and the paths - are searched in the same order. -
-Llinkerflag -
pass linkerflag to the linker, for example, - -M -
-O
-
optimize -
-o-
-
suppress generation of object file -
-odobjdir
-
write object files relative to directory objdir - instead of to the current directory -
-offilename
-
set output file name to filename in the output - directory -
-op
-
normally the path for .d source files is stripped - off when generating an object file name. -op will leave - it on. -
-quiet
-
suppress non-essential compiler messages -
-profile
-
profile - the runtime performance - of the generated code -
-release
-
compile release version -
-unittest
-
compile in unittest code -
-v
-
verbose -
-version=level
-
compile in version code >= level -
-version=ident
-
compile in version code identified by ident -
-w
-
enable warnings -
- -

Linking

- - Linking is done directly by the dmd compiler after a successful - compile. To prevent dmd from running the linker, use the - -c switch. -

- - The actual linking is done by running gcc. - This ensures compatibility with modules compiled with gcc. - -

Environment Variables

- - The D compiler dmd uses the following environment variables: - -
- -
DFLAGS -
The value of DFLAGS is treated as if it were appended to the - command line to dmd. - -
- -

dmd.conf Initialization File

- - dmd will look for the initialization file dmd.conf - in the directory /etc. If found, environment variable - settings in the file will override any existing settings. - This is handy to make dmd independent of programs with - conflicting use of environment variables. -

- - Environment variables follow the [Environment] section - heading, in name=value pairs. Comments are lines that start with ;. - For example: -

-	; dmd.conf file for dmd
-	; Names enclosed by %% are searched for in the existing environment
-	; and inserted. The special name %@P% is replaced with the path
-	; to this file.
-	[Environment]
-	DFLAGS="-I%@P%\..\src\phobos"
-	
- -

Differences from Win32 version

- -
    -
  • String literals are read-only. Attempting to write to them - will cause a segment violation. - -
  • The configuration file is /etc/dmd.conf -
- -

Linux Bugs

- -
    -
  • -g is only implemented for line numbers, not local - symbols, because I haven't figured out how to - do it yet. gdb still works, though, at the global symbol level. - -
  • The code generator output has not been tuned yet, so it - can be bloated. - -
  • Shared libraries cannot be generated. - -
  • The exception handling is not compatible with the way g++ - does it. I don't know if this is an issue or not. -
- -
-

General

- -

Bugs

- - These are some of the major bugs: - -
    - -
  • The compiler sometimes gets the line number wrong on an error. - -
  • The phobos D runtime library is inadequate. - -
  • Need to write a tool to convert C .h files into D imports. - -
  • Array op= operations are not implemented. - -
  • In preconditions and out postconditions for member - functions are not inherited. - -
  • It cannot be run from the IDDE. - -
- -

Questions?

- - We welcome all feedback - kudos, flames, bugs, suggestions, hints, - and most especially donated code! Join the fray in the - D forum. - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - DMD Compiler + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:30 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ + · Overview
+ + + · D for Win32
+ + + · Win32 DLLs in D
+ + + · C .h to D Modules
+ + + · FAQ
+ + + · Style Guide
+ + + · Example: wc
+ + + · Future
+ + + · D Change Log
+ + + · Tech Tips
+ + + · Rationale
+ + + · Glossary
+ + + · Acknowledgements
+ + +
+ Tools +
+ · DMD D Compiler
+ + + · GDC D Compiler
+ + + · Linker
+ + + · Profiler
+ + +
+ Community +
+ · News Digest
+ + + · News
+ + + · Forum
+ + + · Announcements
+ + + · Learn
+ + + · D links
+ + +
+ Archives +
+ · digitalmars.D
+ + + · digitalmars.D.dtl
+ + + · digitalmars.D.announce
+ + + · digitalmars.D.learn
+ + + · digitalmars.D.bugs
+ + + · D.gnu
+ + + · Old D
+ + +
+
+
+ + +

Compiler for D Programming Language

+ + + +

Files Common to Win32 and Linux

+ +
+ +
\dmd\src\phobos\ +
D runtime library source + +
\dmd\src\dmd\ +
D compiler front end source under dual (GPL and Artistic) license + +
\dmd\html\d\ +
Documentation + +
\dmd\samples\d\ +
Sample D programs + +
+ +
+

Win32 D Compiler

+ +

Files

+ +
+ +
\dmd\bin\dmd.exe +
D compiler executable + +
\dmd\bin\shell.exe +
Simple command line shell + +
\dmd\bin\sc.ini +
Global compiler settings + +
\dmd\lib\phobos.lib +
D runtime library + +
+ +

Requirements

+ + + +

Installation

+ + Open a console window (for Windows XP this is done by + clicking on [Start][Command Prompt]). + All the tools are command line tools, which means + they are run from a console window. + Switch to the root directory. + Unzip the files in the root directory. + dmd.zip will create + a \dmd directory with all the files in it. + dmc.zip will create + a \dm directory with all the files in it. +

+ + A typical session might look like: + +

C:\Documents and Settings\Your Name>cd \ 
+C:\>unzip dmd.zip
+C:\>unzip dmc.zip
+
+ +

Example

+ + Run: + +
\dmd\bin\shell all.sh
+
+ + in the \dmd\samples\d directory for several small examples. + +

Compiler Arguments and Switches

+ +
+
dmd files... -switch... +

+

files... +
+ + + + + + + + +
Extension + File Type +
none + D source files +
.d + D source files +
.obj + Object files to link in +
.exe + Name output executable file +
.def + module definition file +
.res + resource file +
+ +
-c
+
compile only, do not link
+ +
-D
+
generate documentation
+ +
-Dddocdir
+
write documentation file to docdir directory
+ +
-Dffilename
+
write documentation file to filename
+ +
-d
+
allow deprecated features +
-debug
+
compile in debug code +
-debug=level
+
compile in debug code <= level +
-debug=ident
+
compile in debug code identified by ident +
-g
+
add symbolic debug info +
-inline +
inline expand functions +
-Ipath +
where to look for imports. path is a ; separated + list of paths. Multiple -I's can be used, and the paths + are searched in the same order. +
-Llinkerflag +
pass linkerflag to the linker, for example, + /ma/li +
-O
+
optimize +
-o-
+
suppress generation of object file +
-odobjdir
+
write object files relative to directory objdir + instead of to the current directory +
-offilename
+
set output file name to filename in the output + directory +
-op
+
normally the path for .d source files is stripped + off when generating an object file name. -op will leave + it on. +
-profile
+
profile + the runtime performance + of the generated code +
-quiet
+
suppress non-essential compiler messages +
-release
+
compile release version, which means not generating + code for contracts and asserts +
-unittest
+
compile in unittest code, also turns on asserts +
-v
+
verbose +
-version=level
+
compile in version code >= level +
-version=ident
+
compile in version code identified by ident +
-w
+
enable warnings +
+ +

Linking

+ + Linking is done directly by the dmd compiler after a successful + compile. To prevent dmd from running the linker, use the + -c switch. +

+ + The programs must be linked with the D runtime library phobos.lib, + followed by the C runtime library snn.lib. + This is done automatically as long as the directories for the + libraries are on the LIB environment variable path. A typical + way to set LIB would be: + +

set LIB=\dmd\lib;\dm\lib
+
+ +

Environment Variables

+ + The D compiler dmd uses the following environment variables: + +
+ +
DFLAGS +
The value of DFLAGS is treated as if it were appended to the + command line to dmd.exe. + +
LIB +
The linker uses LIB to search for library files. For D, it will + normally be set to: + +
set LIB=\dmd\lib;\dm\lib
+
+ +
LINKCMD +
dmd normally runs the linker by looking for link.exe + along the PATH. To use a specific linker instead, set the + LINKCMD environment variable to it. For example: + +
set LINKCMD=\dm\bin\link
+
+ +
PATH +
If the linker is not found in the same directory as dmd.exe + is in, the PATH is searched for it. + Note: other linkers named + link.exe will likely not work. + Make sure the Digital Mars link.exe + is found first in the PATH before other link.exe's, + or use LINKCMD to specifically identify which linker + to use. + +
+ +

SC.INI Initialization File

+ + dmd will look for the initialization file sc.ini in the same + directory dmd.exe resides in. If found, environment variable + settings in the file will override any existing settings. + This is handy to make dmd independent of programs with + conflicting use of environment variables. +

+ + Environment variables follow the [Environment] section + heading, in name=value pairs. Comments are lines that start with ;. + For example: + +

; sc.ini file for dmd
+; Names enclosed by %% are searched for in the existing environment
+; and inserted. The special name %@P% is replaced with the path
+; to this file.
+[Environment]
+LIB="%@P%\..\lib";\dm\lib
+DFLAGS="-I%@P%\..\src\phobos"
+LINKCMD="%@P%\..\..\dm\bin"
+DDOCFILE=mysettings.ddoc
+
+ +

Common Installation Problems

+ +
    +
  • Using Cygwin's unzip utility has been known to cause + strange problems. +
  • Running the compiler under Cygwin's command shell has + been also known to cause problems. Try getting it to work + under the regular Windows shell cmd.exe before trying Cygwin's. +
  • Installing dmd and dmc into directory paths with spaces + in them causes problems. +
+ +
+

Linux D Compiler

+ +

Files

+ +
+ +
/dmd/bin/dmd +
D compiler executable + +
/dmd/bin/dumpobj +
Elf file dumper + +
/dmd/bin/obj2asm +
Elf file disassembler + +
/dmd/bin/dmd.conf +
Global compiler settings (copy to /etc/dmd.conf) + +
/dmd/lib/libphobos.a +
D runtime library (copy to /usr/lib/libphobos.a) + +
+ +

Requirements

+ +
    +
  • 32 bit x86 Linux operating system + +
  • + + D compiler for Linux + +
  • Gnu C compiler (gcc) + +
+ +

Installation

+ +
    + +
  1. Unzip the archive into your home directory. + It will create + a ~/dmd directory with all the files in it. + All the tools are command line tools, which means + they are run from a console window. + +
  2. Edit the file ~/dmd/bin/dmd.conf to put the path in to + where the phobos source files are. + +
  3. Copy dmd.conf to /etc: + +
    cp dmd/bin/dmd.conf /etc
    +
    + +
  4. Give execute permission to the following files: + +
    chmod u+x dmd/bin/dmd dmd/bin/obj2asm dmd/bin/dumpobj
    +
    + +
  5. Put dmd/bin on your PATH, + or copy the linux executables + to /usr/local/bin + +
  6. Copy the library to /usr/lib: + +
    cp dmd/lib/libphobos.a /usr/lib
    +
    +
+ +

Compiler Arguments and Switches

+ +
+
dmd files... -switch... +

+

files... +
+ + + + + + + +
Extension + File Type +
none + D source files +
.d + D source files +
.o + Object files to link in +
.a + Library files to link in +
+ +
-c
+
compile only, do not link
+ +
-D
+
generate documentation
+ +
-Dddocdir
+
write documentation file to docdir directory
+ +
-Dffilename
+
write documentation file to filename
+ +
-d
+
allow deprecated features +
-debug
+
compile in debug code +
-debug=level
+
compile in debug code <= level +
-debug=ident
+
compile in debug code identified by ident +
-g
+
add symbolic debug info +
-gc
+
add symbolic debug info in C format (for older gdb's) +
-inline +
inline expand functions +
-Ipath +
where to look for imports. path is a ; separated + list of paths. Multiple -I's can be used, and the paths + are searched in the same order. +
-Llinkerflag +
pass linkerflag to the linker, for example, + -M +
-O
+
optimize +
-o-
+
suppress generation of object file +
-odobjdir
+
write object files relative to directory objdir + instead of to the current directory +
-offilename
+
set output file name to filename in the output + directory +
-op
+
normally the path for .d source files is stripped + off when generating an object file name. -op will leave + it on. +
-quiet
+
suppress non-essential compiler messages +
-profile
+
profile + the runtime performance + of the generated code +
-release
+
compile release version +
-unittest
+
compile in unittest code +
-v
+
verbose +
-version=level
+
compile in version code >= level +
-version=ident
+
compile in version code identified by ident +
-w
+
enable warnings +
+ +

Linking

+ + Linking is done directly by the dmd compiler after a successful + compile. To prevent dmd from running the linker, use the + -c switch. +

+ + The actual linking is done by running gcc. + This ensures compatibility with modules compiled with gcc. + +

Environment Variables

+ + The D compiler dmd uses the following environment variables: + +
+ +
DFLAGS +
The value of DFLAGS is treated as if it were appended to the + command line to dmd. + +
+ +

dmd.conf Initialization File

+ + dmd will look for the initialization file dmd.conf + in the directory /etc. If found, environment variable + settings in the file will override any existing settings. + This is handy to make dmd independent of programs with + conflicting use of environment variables. +

+ + Environment variables follow the [Environment] section + heading, in name=value pairs. Comments are lines that start with ;. + For example: + +

; dmd.conf file for dmd
+; Names enclosed by %% are searched for in the existing environment
+; and inserted. The special name %@P% is replaced with the path
+; to this file.
+[Environment]
+DFLAGS="-I%@P%\..\src\phobos"
+
+ +

Differences from Win32 version

+ +
    +
  • String literals are read-only. Attempting to write to them + will cause a segment violation. + +
  • The configuration file is /etc/dmd.conf +
+ +

Linux Bugs

+ +
    +
  • -g is only implemented for line numbers, not local + symbols, because I haven't figured out how to + do it yet. gdb still works, though, at the global symbol level. + +
  • The code generator output has not been tuned yet, so it + can be bloated. + +
  • Shared libraries cannot be generated. + +
  • The exception handling is not compatible with the way g++ + does it. I don't know if this is an issue or not. +
+ +
+

General

+ +

Bugs

+ + These are some of the major bugs: + +
    + +
  • The compiler sometimes gets the line number wrong on an error. + +
  • The phobos D runtime library is inadequate. + +
  • Need to write a tool to convert C .h files into D imports. + +
  • Array op= operations are not implemented. + +
  • In preconditions and out postconditions for member + functions are not inherited. + +
  • It cannot be run from the IDDE. + +
+ +

Questions?

+ + We welcome all feedback - kudos, flames, bugs, suggestions, hints, + and most especially donated code! Join the fray in the + D forum. + + +
+ + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/ddoc.html dmd-0.136/dmd/html/d/ddoc.html --- dmd-0.135/dmd/html/d/ddoc.html 2005-09-28 16:59:16.000000000 +0200 +++ dmd-0.136/dmd/html/d/ddoc.html 2005-10-05 19:47:40.000000000 +0200 @@ -1,943 +1,982 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Digital Mars - The D Programming Language - EmbeddedDocumentation - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Wed Sep 28 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - -

Embedded Documentation

- - -The D programming language enables embedding both contracts and test -code along side the actual code, which helps to keep them all -consistent with each other. One thing lacking is the documentation, -as ordinary comments are usually unsuitable for automated extraction -and formatting into manual pages. -Embedding the user documentation into the source code has important -advantages, such as not having to write the documentation twice, and -the likelihood of the documentation staying consistent with the code. -

- -Some existing approaches to this are: - -

- -D's goals for embedded documentation are: - -
    -
  1. It looks good as embedded documentation, not just after it - is extracted and processed. -
  2. It's easy and natural to write, - i.e. minimal reliance on <tags> and other clumsy forms one - would never see in a finished document. -
  3. It does not repeat information that the compiler already - knows from parsing the code. -
  4. It doesn't rely on embedded HTML, as such will impede - extraction and formatting for other purposes. -
  5. It's based on existing D comment forms, so it - is completely independent of parsers only interested in D code. -
  6. It should look and feel different from code, so it won't - be visually confused with code. -
  7. It should be possible for the user to use Doxygen or other - documentation extractor if desired. -
- -

Specification

- -The specification for the form of embedded documentation comments only -specifies how information is to be presented to the compiler. -It is implementation-defined how that information is used and the form -of the final presentation. Whether the final presentation form is an -HTML web page, a man page, a PDF file, etc. is not specified as part of the -D Programming Language. -

- -

Phases of Processing

- -Embedded documentation comments are processed in a series of phases: - -
    -
  1. Lexical - documentation comments are identified and attached - to tokens. -
  2. Parsing - documentation comments are associated with - specific declarations and combined. -
  3. Sections - each documentation comment is divided up into - a sequence of sections. -
  4. Special sections are processed. -
  5. Highlighting of non-special sections is done. -
  6. All sections for the module are combined. -
  7. Macro text substitution is performed to produce the final result. -
- - - -

Lexical

- -Embedded documentation comments are one of the following forms: - -
    -
  1. /** ... */ The two *'s after the opening / -
  2. /++ ... +/ The two +'s after the opening / -
  3. /// The three slashes -
- -The following are all embedded documentation comments: - -
-/// This is a one line documentation comment.
-
-/** So is this. */
-
-/++ And this. +/
-
-/**
-   This is a brief documentation comment.
- */
-
-/**
- * The leading * on this line is not part of the documentation comment.
- */
-
-/*********************************
-   The extra *'s immediately following the /** are not
-   part of the documentation comment.
- */
-
-/++
-   This is a brief documentation comment.
- +/
-
-/++
- + The leading + on this line is not part of the documentation comment.
- +/
-
-/+++++++++++++++++++++++++++++++++
-   The extra +'s immediately following the /++ are not
-   part of the documentation comment.
- +/
-
-/**************** Closing *'s are not part *****************/
-
-
- -The extra *'s and +'s on the comment opening, closing and left margin are -ignored and are not part -of the embedded documentation. -Comments not following one of those forms are not documentation comments. - - -

Parsing

- -Each documentation comment is associated with a declaration. -If the documentation comment is on a line by itself or with only whitespace -to the left, it refers to the next -declaration. -Multiple documentation comments applying to the same declaration -are concatenated. -Documentation comments not associated with a declaration are ignored. -Documentation comments preceding the ModuleDeclaration apply to the -entire module. -If the documentation comment appears on the same line to the right of a -declaration, it applies to that. -

- -If a documentation comment for a declaration consists only of the -identifier ditto -then the documentation comment for the previous declaration at the same -declaration scope is applied to this declaration as well. -

- -If there is no documentation comment for a declaration, that declaration -may not appear in the output. To ensure it does appear in the output, -put an empty declaration comment for it. - -

-int a;  /// documentation for a; b has no documentation
-int b;
-
-/** documentation for c and d */
-/** more documentation for c and d */
-int c;
-/** ditto */
-int d;
-
-/** documentation for e and f */ int e;
-int f;	/// ditto
-
-/** documentation for g */
-int g; /// more documentation for g
-
-/// documentation for C and D
-class C
-{
-    int x;    /// documentation for C.x
-
-    /** documentation for C.y and C.z */
-    int y;
-    int z;    /// ditto
-}
-
-/// ditto
-class D
-{
-}
-
- - - -

Sections

- -The document comment is a series of Sections. -A Section is a name that is the first non-blank character on -a line immediately followed by a ':'. This name forms the section name. -The section name is not case sensitive. -

- -

Summary

- -The first section is the Summary, and does not have a section name. -It is first paragraph, up to a blank line or a section name. -While the summary can be any length, try to keep it to one line. -The Summary section is optional. - -

Description

- -The next unnamed section is the Description. -It consists of all the paragraphs following the Summary until -a section name is encountered or the end of the comment. -

- -While the Description section is optional, -there cannot be a Description without a Summary section. - - -

-/***********************************
- * Brief summary of what
- * myfunc does, forming the summary section.
- *
- * First paragraph of synopsis description.
- *
- * Second paragraph of
- * synopsis description.
- */
-
-void myfunc() { }
-
- -Named sections follow the Summary and Description unnamed sections. - - - -

Standard Sections

- -For consistency and predictability, there are several standard sections. -None of these are required to be present. - -
- -
Authors: -
Lists the author(s) of the declaration. -
-/**
- * Authors: Melvin D. Nerd, melvin@mailinator.com
- */
-
- -
Bugs: -
Lists any known bugs. -
-/**
- * Bugs: Doesn't work for negative values.
- */
-
- -
Date: -
Specifies the date of the current revision. The date should be in a form - parseable by std.date. - -
-/**
- * Date: March 14, 2003
- */
-
- -
Deprecated: -
Provides an explanation for and corrective action to take if the associated - declaration is marked as deprecated. - -
-/**
- * Deprecated: superseded by function bar().
- */
-
-deprecated void foo() { ... }
-
- -
Examples: -
Any usage examples -
-/**
- * Examples:
- * --------------------
- * writefln("3"); // writes '3' to stdout
- * --------------------
- */
-
- -
History: -
Revision history. -
-/**
- * History:
- *	V1 is initial version
- *
- *	V2 added feature X
- */
-
- -
License: -
Any license information for copyrighted code. -
-/**
- * License: use freely for any purpose
- */
-
-void bar() { ... }
-
- -
Returns: -
Explains the return value of the function. - If the function returns void, don't redundantly document it. -
-/**
- * Read the file.
- * Returns: The contents of the file.
- */
-
-void[] readFile(char[] filename) { ... }
-
- -
See_Also: -
List of other symbols and URL's to related items. -
-/**
- * See_Also:
- *    foo, bar, http://www.digitalmars.com/d/phobos/index.html
- */
-
- -
Standards: -
If this declaration is compliant with any particular standard, -the description of it goes here. -
-/**
- * Standards: Conforms to DSPEC-1234
- */
-
- -
Throws: -
Lists exceptions thrown and under what circumstances they are thrown. -
-/**
- * Write the file.
- * Throws: WriteException on failure.
- */
-
-void writeFile(char[] filename) { ... }
-
- -
Version: -
Specifies the current version of the declaration. -
-/**
- * Version: 1.6a
- */
-
- -
- - - -

Special Sections

- -Some sections have specialized meanings and syntax. - -
- -
Copyright: -
This contains the copyright notice. The macro COPYRIGHT is set to - the contents of the section when it documents the module declaration. - The copyright section only gets this special treatment when it - is for the module declaration. - -
-/** Copyright: Public Domain */
-
-module foo;
-
- -
Params: -
Function parameters can be documented by listing them in a params - section. Each line that starts with an identifier followed by - an '=' starts a new parameter description. A description can - span multiple lines. - -
-/***********************************
- * foo does this.
- * Params:
- *	x =	is for this
- *		and not for that
- *	y =	is for that
- */
-
-void foo(int x, int y)
-{
-}
-
- -
Macros:
-
The macros section follows the same syntax as the Params: section. - It's a series of NAME=value pairs. - The NAME is the macro name, and value is the replacement - text. -
-/**
- * Macros:
- *	FOO =	now is the time for
- *		all good men
- *	BAR =	bar
- *	MAGENTA =   <font color=magenta>$0</font>
- */
-
- -
- - -

Highlighting

- - - -

Embedded Comments

- - The documentation comments can themselves be commented using - the <!-- comment text --> syntax. These comments do not - nest. - -

Embedded Code

- - D code can be embedded using lines with at least three -'s in - them to delinate the code section: - -
-/++++++++++++++++++++++++
- + Our function.
- + Example:
- + --------------------------
- +  #include <stdio.h>
- +
- +  void foo()
- +  {
- +	printf("foo!\n");  /* print the string */
- +  }
- + --------------------------
- +/
-
- - Note that documentation comment uses the /++ ... +/ form - so that /* ... */ can be used inside the code section. - -

Embedded HTML

- -HTML can be embedded into the documentation comments, and it will -be passed through to the HTML output unchanged. -However, since it is not necessarily true that HTML will be the desired -output format of the embedded documentation comment extractor, it is -best to avoid using it where practical. - -
-/** Example of embedded HTML:
- *   <ol>
- *      <li> <a href="www.digitalmars.com">Digital Mars</a>
- *      <li> <a href="www.classicempire.com">Empire</a>
- *   </ol>
- */
-
- - -

Emphasis

- -Identifiers in documentation comments that are function parameters or are -names that are in scope at the associated declaration are emphasized in -the output. -This emphasis can take the form of italics, boldface, a hyperlink, etc. -How it is emphasized depends on what it is - a function parameter, type, -D keyword, etc. -To prevent unintended emphasis of an identifier, it can be preceded by -an underscore (_). The underscore will be stripped from the output. - - -

Character Entities

- - Because the characters <, > and & have special meaning - to the documentation processor, to avoid confusion it can be best - to replace them with their corresponding character entities: -

- - - - - - -
Character Entity
< &lt;
> &gt;
& &amp;
-

- - It is not necessary to do this inside a code section, or if the - special character is not immediately followed by a # or a letter. - -

Macros

- - The documentation comment processor includes a simple macro - text preprocessor. - When a appears - in section text it is replaced with NAME's corresponding - replacment text. - The replacement text is then recursively scanned for more macros. - If a macro is recursively encountered, with no argument or with - the same argument text as the enclosing macro, it is replaced - with no text. - Macro invocations that cut across replacement text boundaries are - not expanded. - If the macro name is undefined, the replacement text has no characters - in it. - If a is desired to exist in the output without being macro - expanded, add an extra $ as in: $(NAME). The extra $ will be elided. -

- - Macros can have arguments. Any text from the end of the identifier - to the closing ')' is the $0 argument. A $0 in the replacement text is - replaced with the argument text. - If there are commas in the argument text, $1 will represent the - argument text up to the first comma, $2 from the first comma to - the second comma, etc., up to $9. - $+ represents the text from the first comma to the closing ')'. - The argument text can contain nested parentheses, "" or '' strings, - comments, or tags. -

- - Macro definitions come from the following sources, - in the specified order: - -

    -
  1. Predefined macros. -
  2. Definitions from file specified by sc.ini's DDOCFILE setting. -
  3. Definitions from *.ddoc files specified on the command line. -
  4. Runtime definitions generated by Ddoc. -
  5. Definitions from any Macros: sections. -
- - Macro redefinitions replace previous definitions of the same name. - This means that the sequence of macro definitions from the various - sources forms a heirarchy. -

- - Macro names beginning with "D_" and "DDOC_" are reserved. - -

Predefined Macros

- - These are hardwired into Ddoc, and represent the - minimal definitions needed by Ddoc to format and highlight - the presentation. - The definitions are for simple HTML. - -
-B =	<b>$0</b>
-I =	<i>$0</i>
-U =	<u>$0</u>
-P =	<p>$0</p>
-DL =	<dl>$0</dl>
-DT =	<dt>$0</dt>
-DD =	<dd>$0</dd>
-TABLE =	<table>$0</table>
-TR =	<tr>$0</tr>
-TH =	<th>$0</th>
-TD =	<td>$0</td>
-OL =	<ol>$0</ol>
-UL =	<ul>$0</ul>
-LI =	<li>$0</li>
-BIG =	<big>$0</big>
-SMALL =	<small>$0</small>
-BR =	<br>
-LINK =	<a href="$0">$0</a>
-LINK2 =	<a href="$1">$+</a>
-
-RED =	<font color=red>$0</font>
-BLUE =	<font color=blue>$0</font>
-GREEN =	<font color=green>$0</font>
-YELLOW =<font color=yellow>$0</font>
-BLACK =	<font color=black>$0</font>
-WHITE =	<font color=white>$0</font>
-
-D_CODE = <pre class="d_code">$0</pre>
-
-DDOC =	<html><head>
-	<META http-equiv="content-type" content="text/html; charset=utf-8">
-	<title>$(TITLE)</title>
-	</head><body>
-	<h1>$(TITLE)</h1>
-	$(BODY)
-	</body></html>
-
-DDOC_DECL      = $(DT $(BIG $0))
-DDOC_DECL_DD   = $(DD $0)
-DDOC_SECTIONS  = $0
-DDOC_SUMMARY   = $0$(BR)$(BR)
-DDOC_DESCRIPTION = $0$(BR)$(BR)
-DDOC_AUTHORS   = $(B Authors:)$(BR)
-		$0$(BR)$(BR)
-DDOC_BUGS      = $(RED BUGS:)$(BR)
-		$0$(BR)$(BR)
-DDOC_COPYRIGHT = $(B Copyright:)$(BR)
-		$0$(BR)$(BR)
-DDOC_DATE      = $(B Date:)$(BR)
-		$0$(BR)$(BR)
-DDOC_DEPRECATED = $(RED Deprecated:)$(BR)
-		$0$(BR)$(BR)
-DDOC_EXAMPLES  = $(B Examples:)$(BR)
-		$0$(BR)$(BR)
-DDOC_HISTORY   = $(B History:)$(BR)
-		$0$(BR)$(BR)
-DDOC_LICENSE   = $(B License:)$(BR)
-		$0$(BR)$(BR)
-DDOC_RETURNS   = $(B Returns:)$(BR)
-		$0$(BR)$(BR)
-DDOC_SEE_ALSO  = $(B See Also:)$(BR)
-		$0$(BR)$(BR)
-DDOC_STANDARDS = $(B Standards:)$(BR)
-		$0$(BR)$(BR)
-DDOC_THROWS    = $(B Throws:)$(BR)
-		$0$(BR)$(BR)
-DDOC_VERSION   = $(B Version:)$(BR)
-		$0$(BR)$(BR)
-DDOC_SECTION_H = $(B $0)$(BR)$(BR)
-DDOC_SECTION   = $0$(BR)$(BR)
-DDOC_MEMBERS   = $(DL $0)
-DDOC_PARAMS    = $(TABLE $0)$(BR)$(BR)
-DDOC_PARAM_ROW = $(TR $0)
-DDOC_PARAM_ID  = $(TD $0)
-DDOC_PARAM_DESC  = $(TD $0)
-
-DDOC_PSYMBOL	= $(U $0)
-DDOC_KEYWORD	= $(B $0)
-DDOC_PARAM	= $(I $0)
-	
- - Ddoc does not generate HTML code. It formats into the basic - formatting macros, which (in their predefined form) - are then expanded into HTML. - If output other than HTML is desired, then these macros - need to be redefined. -

- - - -
Basic Formatting Macros
B boldface the argument -
I italicize the argument -
U underline the argument -
P argument is a paragraph -
DL argument is a definition list -
DT argument is a definition in a definition list -
DD argument is a description of a definition -
TABLE argument is a table -
TR argument is a row in a table -
TH argument is a header entry in a row -
TD argument is a data entry in a row -
OL argument is an ordered list -
UL argument is an unordered list -
LI argument is an item in a list -
BIG argument is one font size bigger -
SMALL argument is one font size smaller -
BR start new line -
LINK generate clickable link on argument -
LINK2 generate clickable link, first arg is address -
RED argument is set to be red -
BLUE argument is set to be blue -
GREEN argument is set to be green -
YELLOW argument is set to be yellow -
BLACK argument is set to be black -
WHITE argument is set to be white -
D_CODE argument is D code -
DDOC overall template for output -
-

- - DDOC is special in that it specifies the boilerplate into - which the entire generated text is inserted (represented by the - Ddoc generated macro BODY). For example, in order - to use a style sheet, DDOC would be redefined as: - -

-DDOC =	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-	<html><head>
-	<META http-equiv="content-type" content="text/html; charset=utf-8">
-	<title>$(TITLE)</title>
-	<link rel="stylesheet" type="text/css" href="style.css">
-	</head><body>
-	<h1>$(TITLE)</h1>
-	$(BODY)
-	</body></html>
-	
- - The highlighting macros start with DDOC_. - They control the formatting of individual parts of the presentation. -

- - -
DDOC_DECL - Highlighting of the declaration. - -
DDOC_DECL_DD - Highlighting of the description of a declaration. - -
DDOC_SECTIONS - Highlighting of all the sections. - -
DDOC_SUMMARY - Highlighting of the summary section. - -
DDOC_DESCRIPTION - Highlighting of the description section. - -
DDOC_AUTHORS .. DDOC_VERSION - Highlighting of the corresponding standard section. - -
DDOC_SECTION_H - Highlighting of the section name of a non-standard section. - -
DDOC_SECTION - Highlighting of the contents of a non-standard section. - -
DDOC_MEMBERS - Highlighting of all the members of a class, struct, etc. - -
DDOC_PARAMS - Highlighting of a function parameter section. - -
DDOC_PARAM_ROW - Highlighting of a name=value function parameter. - -
DDOC_PARAM_ID - Highlighting of the parameter name. - -
DDOC_PARAM_DESC - Highlighting of the parameter value. - -
DDOC_PSYMBOL - Highlighting of declaration name to which a particular section is - referring. - -
DDOC_KEYWORD - Highlighting of D keywords. - -
DDOC_PARAM - Highlighting of function parameters. -
-

- - For example, one could redefine DDOC_SUMMARY: - -

-DDOC_SECTIONS  = $(GREEN $0)
-	
- - And all the description sections will now be green. - -

Macro Definitions from sc.ini's DDOCFILE

- - A text file of macro definitions can be created, - and specified in sc.ini: - -
-DDOCFILE=myproject.ddoc
-	
- -

Macro Definitions from .ddoc Files on the Command Line

- - File names on the DMD command line with the extension - .ddoc are text files that are read and processed in order. - -

Macro Definitions Generated by Ddoc

- - - - - - - -
BODY - Set to the generated document text. -
TITLE - Set to the module name. -
DATETIME - Set to the current date and time. -
YEAR - Set to the current year. -
COPYRIGHT - Set to the contents of any Copyright: section that is part - of the module comment. -
- - - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - - - + + + + + + + + +Digital Mars - The D Programming Language - Documentation Generator + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Wed Oct 5 19:47:39 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+

Embedded Documentation

+ +

The D programming language enables embedding both contracts and test +code along side the actual code, which helps to keep them all +consistent with each other. One thing lacking is the documentation, +as ordinary comments are usually unsuitable for automated extraction +and formatting into manual pages. +Embedding the user documentation into the source code has important +advantages, such as not having to write the documentation twice, and +the likelihood of the documentation staying consistent with the code. +

+ +

Some existing approaches to this are: +

+ + + +

D's goals for embedded documentation are: +

+ +
    +
  1. It looks good as embedded documentation, not just after it + is extracted and processed. +
  2. It's easy and natural to write, + i.e. minimal reliance on <tags> and other clumsy forms one + would never see in a finished document. +
  3. It does not repeat information that the compiler already + knows from parsing the code. +
  4. It doesn't rely on embedded HTML, as such will impede + extraction and formatting for other purposes. +
  5. It's based on existing D comment forms, so it + is completely independent of parsers only interested in D code. +
  6. It should look and feel different from code, so it won't + be visually confused with code. +
  7. It should be possible for the user to use Doxygen or other + documentation extractor if desired. +
+ +

Specification

+ +

The specification for the form of embedded documentation comments only +specifies how information is to be presented to the compiler. +It is implementation-defined how that information is used and the form +of the final presentation. Whether the final presentation form is an +HTML web page, a man page, a PDF file, etc. is not specified as part of the +D Programming Language. +

+ +

Phases of Processing

+ +

Embedded documentation comments are processed in a series of phases: +

+ +
    +
  1. Lexical - documentation comments are identified and attached + to tokens. +
  2. Parsing - documentation comments are associated with + specific declarations and combined. +
  3. Sections - each documentation comment is divided up into + a sequence of sections. +
  4. Special sections are processed. +
  5. Highlighting of non-special sections is done. +
  6. All sections for the module are combined. +
  7. Macro text substitution is performed to produce the final result. +
+ +

Lexical

+ +

Embedded documentation comments are one of the following forms: +

+ +
    +
  1. /** ... */ The two *'s after the opening / +
  2. /++ ... +/ The two +'s after the opening / +
  3. /// The three slashes +
+ +

The following are all embedded documentation comments:

+ +
/// This is a one line documentation comment.
+
+/** So is this. */
+
+/++ And this. +/
+
+/**
+   This is a brief documentation comment.
+ */
+
+/**
+ * The leading * on this line is not part of the documentation comment.
+ */
+
+/*********************************
+   The extra *'s immediately following the /** are not
+   part of the documentation comment.
+ */
+
+/++
+   This is a brief documentation comment.
+ +/
+
+/++
+ + The leading + on this line is not part of the documentation comment.
+ +/
+
+/+++++++++++++++++++++++++++++++++
+   The extra +'s immediately following the / ++ are not
+   part of the documentation comment.
+ +/
+
+/**************** Closing *'s are not part *****************/
+
+ +

The extra *'s and +'s on the comment opening, closing and left margin are +ignored and are not part +of the embedded documentation. +Comments not following one of those forms are not documentation comments. +

+ +

Parsing

+ +

Each documentation comment is associated with a declaration. +If the documentation comment is on a line by itself or with only whitespace +to the left, it refers to the next +declaration. +Multiple documentation comments applying to the same declaration +are concatenated. +Documentation comments not associated with a declaration are ignored. +Documentation comments preceding the ModuleDeclaration apply to the +entire module. +If the documentation comment appears on the same line to the right of a +declaration, it applies to that. +

+ +

If a documentation comment for a declaration consists only of the +identifier ditto +then the documentation comment for the previous declaration at the same +declaration scope is applied to this declaration as well. +

+ +

If there is no documentation comment for a declaration, that declaration +may not appear in the output. To ensure it does appear in the output, +put an empty declaration comment for it. +

+ +
int a;  /// documentation for a; b has no documentation
+int b;
+
+/** documentation for c and d */
+/** more documentation for c and d */
+int c;
+/** ditto */
+int d;
+
+/** documentation for e and f */ int e;
+int f;	/// ditto
+
+/** documentation for g */
+int g; /// more documentation for g
+
+/// documentation for C and D
+class C
+{
+    int x;    /// documentation for C.x
+
+    /** documentation for C.y and C.z */
+    int y;
+    int z;    /// ditto
+}
+
+/// ditto
+class D
+{
+}
+
+ +

Sections

+ +

The document comment is a series of Sections. +A Section is a name that is the first non-blank character on +a line immediately followed by a ':'. This name forms the section name. +The section name is not case sensitive. +

+ +

Summary

+ +

The first section is the Summary, and does not have a section name. +It is first paragraph, up to a blank line or a section name. +While the summary can be any length, try to keep it to one line. +The Summary section is optional. +

+ +

Description

+ +

The next unnamed section is the Description. +It consists of all the paragraphs following the Summary until +a section name is encountered or the end of the comment. +

+ +

While the Description section is optional, +there cannot be a Description without a Summary section. +

+ +
/***********************************
+ * Brief summary of what
+ * myfunc does, forming the summary section.
+ *
+ * First paragraph of synopsis description.
+ *
+ * Second paragraph of
+ * synopsis description.
+ */
+
+void myfunc() { }
+
+ +

Named sections follow the Summary and Description unnamed sections. +

+ +

Standard Sections

+ +

For consistency and predictability, there are several standard sections. +None of these are required to be present. +

+ +
+ +
Authors: +
Lists the author(s) of the declaration. +
/**
+ * Authors: Melvin D. Nerd, melvin@mailinator.com
+ */
+
+ +
Bugs: +
Lists any known bugs. +
/**
+ * Bugs: Doesn't work for negative values.
+ */
+
+ +
Date: +
Specifies the date of the current revision. The date should be in a form + parseable by std.date. + +
/**
+ * Date: March 14, 2003
+ */
+
+ +
Deprecated: +
Provides an explanation for and corrective action to take if the associated + declaration is marked as deprecated. + +
/**
+ * Deprecated: superseded by function bar().
+ */
+
+deprecated void foo() { ... }
+
+ +
Examples: +
Any usage examples +
/**
+ * Examples:
+ * --------------------
+ * writefln("3"); // writes '3' to stdout
+ * --------------------
+ */
+
+ +
History: +
Revision history. +
/**
+ * History:
+ *	V1 is initial version
+ *
+ *	V2 added feature X
+ */
+
+ +
License: +
Any license information for copyrighted code. +
/**
+ * License: use freely for any purpose
+ */
+
+void bar() { ... }
+
+ +
Returns: +
Explains the return value of the function. + If the function returns void, don't redundantly document it. +
/**
+ * Read the file.
+ * Returns: The contents of the file.
+ */
+
+void[] readFile(char[] filename) { ... }
+
+ +
See_Also: +
List of other symbols and URL's to related items. +
/**
+ * See_Also:
+ *    foo, bar, http://www.digitalmars.com/d/phobos/index.html
+ */
+
+ +
Standards: +
If this declaration is compliant with any particular standard, +the description of it goes here. +
/**
+ * Standards: Conforms to DSPEC-1234
+ */
+
+ +
Throws: +
Lists exceptions thrown and under what circumstances they are thrown. +
/**
+ * Write the file.
+ * Throws: WriteException on failure.
+ */
+
+void writeFile(char[] filename) { ... }
+
+ +
Version: +
Specifies the current version of the declaration. +
/**
+ * Version: 1.6a
+ */
+
+
+ +

Special Sections

+ +

Some sections have specialized meanings and syntax. +

+ +
+ +
Copyright: +
This contains the copyright notice. The macro COPYRIGHT is set to + the contents of the section when it documents the module declaration. + The copyright section only gets this special treatment when it + is for the module declaration. + +
/** Copyright: Public Domain */
+
+module foo;
+
+ +
Params: +
Function parameters can be documented by listing them in a params + section. Each line that starts with an identifier followed by + an '=' starts a new parameter description. A description can + span multiple lines. + +
/***********************************
+ * foo does this.
+ * Params:
+ *	x =	is for this
+ *		and not for that
+ *	y =	is for that
+ */
+
+void foo(int x, int y)
+{
+}
+
+ +
Macros:
+
The macros section follows the same syntax as the Params: section. + It's a series of NAME=value pairs. + The NAME is the macro name, and value is the replacement + text. +
/**
+ * Macros:
+ *	FOO =	now is the time for
+ *		all good men
+ *	BAR =	bar
+ *	MAGENTA =   &lt;font color=magenta&gt;&lt;/font&gt;
+ */
+
+
+ +

Highlighting

+ +

Embedded Comments

+ +

The documentation comments can themselves be commented using + the <!-- comment text --> syntax. These comments do not + nest. +

+ +

Embedded Code

+ +

D code can be embedded using lines with at least three -'s in + them to delineate the code section: +

+ +
 /++++++++++++++++++++++++
+  + Our function.
+  + Example:
+  + --------------------------
+  +  #include <stdio.h>
+  +
+  +  void foo()
+  +  {
+  +	printf("foo!\n");  /* print the string */
+  +  }
+  + --------------------------
+  +/
+
+ +

Note that documentation comment uses the /++ ... +/ form + so that /* ... */ can be used inside the code section. +

+ +

Embedded HTML

+ +

HTML can be embedded into the documentation comments, and it will +be passed through to the HTML output unchanged. +However, since it is not necessarily true that HTML will be the desired +output format of the embedded documentation comment extractor, it is +best to avoid using it where practical. +

+ +
/** Example of embedded HTML:
+ *   <ol>
+ *      <li> <a href="www.digitalmars.com">Digital Mars</a>
+ *      <li> <a href="www.classicempire.com">Empire</a>
+ *   </ol>
+ */
+
+ +

Emphasis

+ +

Identifiers in documentation comments that are function parameters or are +names that are in scope at the associated declaration are emphasized in +the output. +This emphasis can take the form of italics, boldface, a hyperlink, etc. +How it is emphasized depends on what it is - a function parameter, type, +D keyword, etc. +To prevent unintended emphasis of an identifier, it can be preceded by +an underscore (_). The underscore will be stripped from the output. +

+ +

Character Entities

+ +

Some characters have special meaning + to the documentation processor, to avoid confusion it can be best + to replace them with their corresponding character entities: +

+ + + + + + +
Character Entity
< &lt;
> &gt;
& &amp;
+ +

It is not necessary to do this inside a code section, or if the + special character is not immediately followed by a # or a letter. +

+ +

Macros

+ +

The documentation comment processor includes a simple macro + text preprocessor. + When a $(NAME) appears + in section text it is replaced with NAME's corresponding + replacment text. + The replacement text is then recursively scanned for more macros. + If a macro is recursively encountered, with no argument or with + the same argument text as the enclosing macro, it is replaced + with no text. + Macro invocations that cut across replacement text boundaries are + not expanded. + If the macro name is undefined, the replacement text has no characters + in it. + If a $(NAME) is desired to exist in the output without being + macro expanded, the $ should be replaced with &#36;. +

+ +

Macros can have arguments. Any text from the end of the identifier + to the closing ')' is the $0 argument. + A $0 in the replacement text is + replaced with the argument text. + If there are commas in the argument text, $1 will represent the + argument text up to the first comma, $2 from the first comma to + the second comma, etc., up to $9. + $+ represents the text from the first comma to the closing ')'. + The argument text can contain nested parentheses, "" or '' strings, + comments, or tags. + If stray, unnested parentheses are used, they can be replaced with + the entity &#40; for ( and &#41; for ). +

+ +

Macro definitions come from the following sources, + in the specified order: +

+ +
    +
  1. Predefined macros. +
  2. Definitions from file specified by sc.ini's DDOCFILE setting. +
  3. Definitions from *.ddoc files specified on the command line. +
  4. Runtime definitions generated by Ddoc. +
  5. Definitions from any Macros: sections. +
+ +

Macro redefinitions replace previous definitions of the same name. + This means that the sequence of macro definitions from the various + sources forms a heirarchy. +

+ +

Macro names beginning with "D_" and "DDOC_" are reserved. +

+ +

Predefined Macros

+ +

These are hardwired into Ddoc, and represent the + minimal definitions needed by Ddoc to format and highlight + the presentation. + The definitions are for simple HTML. +

+ +
B =	<b>$0</b>
+I =	<i>$0</i>
+U =	<u>$0</u>
+P =	<p>$0</p>
+DL =	<dl>$$0</dl>
+DT =	<dt>$0</dt>
+DD =	<dd>$0</dd>
+TABLE =	<table>$0</table>
+TR =	<tr>$0</tr>
+TH =	<th>$0</th>
+TD =	<td>$0</td>
+OL =	<ol>$0</ol>
+UL =	<ul>$0</ul>
+LI =	<li>$0</li>
+BIG =	<big>$0</big>
+SMALL =	<small>$0</small>
+BR =	<br>
+LINK =	<a href="$0">$0</a>
+LINK2 =	<a href="$1">$+</a>
+
+RED =	<font color=red>$0</font>
+BLUE =	<font color=blue>$0</font>
+GREEN =	<font color=green>$0</font>
+YELLOW =<font color=yellow>$0</font>
+BLACK =	<font color=black>$0</font>
+WHITE =	<font color=white>$0</font>
+
+D_CODE = <pre class="d_code">$0</pre>
+D_COMMENT = $(GREEN $0)
+D_STRING  = $(RED $0)
+D_KEYWORD = $(BLUE $0)
+D_PSYMBOL = $(U $0)
+D_PARAM	  = $(I $0)
+
+DDOC =	<html><head>
+	<META http-equiv="content-type" content="text/html; charset=utf-8">
+	<title>$(TITLE)</title>
+	</head><body>
+	<h1>$(TITLE)</h1>
+	$(BODY)
+	</body></html>
+
+DDOC_DECL      = $(DT $(BIG $0))
+DDOC_DECL_DD   = $(DD $0)
+DDOC_SECTIONS  = $0
+DDOC_SUMMARY   = $0$(BR)$(BR)
+DDOC_DESCRIPTION = $0$(BR)$(BR)
+DDOC_AUTHORS   = $(B Authors:)$(BR)
+		$0$(BR)$(BR)
+DDOC_BUGS      = $(RED BUGS:)$(BR)
+		$0$(BR)$(BR)
+DDOC_COPYRIGHT = $(B Copyright:)$(BR)
+		$0$(BR)$(BR)
+DDOC_DATE      = $(B Date:)$(BR)
+		$0$(BR)$(BR)
+DDOC_DEPRECATED = $(RED Deprecated:)$(BR)
+		$0$(BR)$(BR)
+DDOC_EXAMPLES  = $(B Examples:)$(BR)
+		$0$(BR)$(BR)
+DDOC_HISTORY   = $(B History:)$(BR)
+		$0$(BR)$(BR)
+DDOC_LICENSE   = $(B License:)$(BR)
+		$0$(BR)$(BR)
+DDOC_RETURNS   = $(B Returns:)$(BR)
+		$0$(BR)$(BR)
+DDOC_SEE_ALSO  = $(B See Also:)$(BR)
+		$0$(BR)$(BR)
+DDOC_STANDARDS = $(B Standards:)$(BR)
+		$0$(BR)$(BR)
+DDOC_THROWS    = $(B Throws:)$(BR)
+		$0$(BR)$(BR)
+DDOC_VERSION   = $(B Version:)$(BR)
+		$0$(BR)$(BR)
+DDOC_SECTION_H = $(B $0)$(BR)$(BR)
+DDOC_SECTION   = $0$(BR)$(BR)
+DDOC_MEMBERS   = $(DL $0)
+DDOC_PARAMS    = $(TABLE $0)$(BR)$(BR)
+DDOC_PARAM_ROW = $(TR $0)
+DDOC_PARAM_ID  = $(TD $0)
+DDOC_PARAM_DESC  = $(TD $0)
+DDOC_BLANKLINE	= $(BR)$(BR)
+
+DDOC_PSYMBOL	= $(U $0)
+DDOC_KEYWORD	= $(B $0)
+DDOC_PARAM	= $(I $0)
+
+ +

Ddoc does not generate HTML code. It formats into the basic + formatting macros, which (in their predefined form) + are then expanded into HTML. + If output other than HTML is desired, then these macros + need to be redefined. +

+ + + +
Basic Formatting Macros
B boldface the argument +
I italicize the argument +
U underline the argument +
P argument is a paragraph +
DL argument is a definition list +
DT argument is a definition in a definition list +
DD argument is a description of a definition +
TABLE argument is a table +
TR argument is a row in a table +
TH argument is a header entry in a row +
TD argument is a data entry in a row +
OL argument is an ordered list +
UL argument is an unordered list +
LI argument is an item in a list +
BIG argument is one font size bigger +
SMALL argument is one font size smaller +
BR start new line +
LINK generate clickable link on argument +
LINK2 generate clickable link, first arg is address +
RED argument is set to be red +
BLUE argument is set to be blue +
GREEN argument is set to be green +
YELLOW argument is set to be yellow +
BLACK argument is set to be black +
WHITE argument is set to be white +
D_CODE argument is D code +
DDOC overall template for output +
+

+ +

DDOC is special in that it specifies the boilerplate into + which the entire generated text is inserted (represented by the + Ddoc generated macro BODY). For example, in order + to use a style sheet, DDOC would be redefined as: +

+ +
DDOC =	<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+	<html><head>
+	<META http-equiv="content-type" content="text/html; charset=utf-8">
+	<title>$(TITLE)</title>
+	<link rel="stylesheet" type="text/css" href="style.css">
+	</head><body>
+	<h1>$(TITLE)</h1>
+	$(BODY)
+	</body></html>
+
+ +

Highlighting of D code is performed by the following macros: +

+ + + +
D Code Formatting Macros
D_COMMENT Highlighting of comments +
D_STRING Highlighting of string literals +
D_KEYWORD Highlighting of D keywords +
D_PSYMBOL Highlighting of current declaration name +
D_PARAM Highlighting of current function declaration parameters +
+ +

The highlighting macros start with DDOC_. + They control the formatting of individual parts of the presentation. +

+ + +
DDOC_DECL + Highlighting of the declaration. +
DDOC_DECL_DD + Highlighting of the description of a declaration. +
DDOC_SECTIONS + Highlighting of all the sections. +
DDOC_SUMMARY + Highlighting of the summary section. +
DDOC_DESCRIPTION + Highlighting of the description section. +
DDOC_AUTHORS .. DDOC_VERSION + Highlighting of the corresponding standard section. +
DDOC_SECTION_H + Highlighting of the section name of a non-standard section. +
DDOC_SECTION + Highlighting of the contents of a non-standard section. +
DDOC_MEMBERS + Highlighting of all the members of a class, struct, etc. +
DDOC_PARAMS + Highlighting of a function parameter section. +
DDOC_PARAM_ROW + Highlighting of a name=value function parameter. +
DDOC_PARAM_ID + Highlighting of the parameter name. +
DDOC_PARAM_DESC + Highlighting of the parameter value. +
DDOC_PSYMBOL + Highlighting of declaration name to which a particular section is + referring. +
DDOC_KEYWORD + Highlighting of D keywords. +
DDOC_PARAM + Highlighting of function parameters. +
DDOC_BLANKLINE + Inserts a blank line. +
+

+ +

For example, one could redefine DDOC_SUMMARY: +

+ +
DDOC_SUMMARY = $(GREEN $0)
+
+ +

And all the summary sections will now be green. +

+ +

Macro Definitions from sc.ini's DDOCFILE

+ +

A text file of macro definitions can be created, + and specified in sc.ini: +

+ +
DDOCFILE=myproject.ddoc
+
+ +

Macro Definitions from .ddoc Files on the Command Line

+ +

File names on the DMD command line with the extension + .ddoc are text files that are read and processed in order. +

+ +

Macro Definitions Generated by Ddoc

+ + + + + + + +
BODY + Set to the generated document text. +
TITLE + Set to the module name. +
DATETIME + Set to the current date and time. +
YEAR + Set to the current year. +
COPYRIGHT + Set to the contents of any Copyright: section that is part + of the module comment. +
+ +

Using Ddoc for other Documentation

+ +

Ddoc is primarilly designed for use in producing documentation + from embedded comments. It can also, however, be used for + processing other general documentation. + The reason for doing this would be to take advantage of the + macro capability of Ddoc and the D code syntax highlighting + capability. +

+ +

If the .d source file starts with the string "Ddoc" then it + is treated as general purpose documentation, not as a D + code source file. From immediately after the "Ddoc" string + to the end of the file or any "Macros:" section forms + the document. No automatic highlighting is done to that text, + other than highlighting of D code embedded between lines + delineated with --- lines. Only macro processing is done. +

+ +

Much of the D documentation itself is generated this way, + including this page. + Such documentation is marked at the bottom as being + generated by Ddoc. +

+ +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/declaration.html dmd-0.136/dmd/html/d/declaration.html --- dmd-0.135/dmd/html/d/declaration.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/declaration.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,549 +1,581 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Declarations - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - -

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
-        Parameter , ParameterList
-        ...
-
-Parameter:
-        Declarator
-        Declarator = AssignExpression
-        InOut Declarator
-        InOut Declarator = AssignExpression
-
-InOut:
-        in
-        out
-        inout
-
-Initializer:
-        void
-        AssignExpression
-        ArrayInitializer
-        StructInitializer
-
-
- -

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

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').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
-    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.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Declarations + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ +

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
+        Parameter , ParameterList
+        ...
+
+Parameter:
+        Declarator
+        Declarator = AssignExpression
+        InOut Declarator
+        InOut Declarator = AssignExpression
+
+InOut:
+        in
+        out
+        inout
+
+Initializer:
+        void
+        AssignExpression
+        ArrayInitializer
+        StructInitializer
+
+
+ +

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

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').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
+    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. +

+ + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/dlinks.html dmd-0.136/dmd/html/d/dlinks.html --- dmd-0.135/dmd/html/d/dlinks.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/dlinks.html 2005-10-08 22:10:30.000000000 +0200 @@ -1,529 +1,589 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Digital Mars - The D Programming Language - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - -

D Links

- - -

Wikis

- - - -

Tools

- -
    -
  • D-mode - an emacs mode for D - -
  • - DMD Front End Starter Kit - -
  • akIDE - is an open source IDE written in D. Comes with D syntax colouring, D - project wizard and DMD compiler support. - -
  • Andy Friesen has taken - SWIG - and - modified it to generate code for D. - -
  • - Zeus for Windows - comes with D compiler (*) and keywords predefined and - has a ctags program (xtags.exe) that supports the D language. - (*) For the D compiler to work within Zeus the user will need - to download and install the compiler from www.digitalmars.com/d/. If - it is already installed it should be automatic. - -
  • Program editors - customized for use with D. - -
  • Build - tool for building D executables and libraries. - -
  • DStress - language conformance test suite. -
- -

Libraries

- -
    -
  • MinTL - a container library - -
  • Locks - a concurrent programming library - -
  • MinWin - a GUI toolkit - -
  • gmp-d - a D interface for GMP multi-precision float and big-integer library - -
  • SynSoft's D Page provides - a number of free D libraries. SynSoft is an imprint of - Synesis Software, - which provides free D, - Java, .NET, Perl and Python libraries. SynSoft has contributed several - modules to the D standard library, and is currently working on a - standard template library - the DTL. - -
  • Mango - for server side programming. - -
  • D MySQL Binding for Linux. - -
  • - D graphical User Interface (DUI) toolkit. - -
  • Simple URL loading - library by Burton Radons. - Requires the DIG library - to be installed, although it doesn't use it, just digc. - Comes with documentation. - It has the functions: -
      -
    • urlopen: Open a URL as a stream (http, file, and ftp schema supported). -
    • urlread: Open a URL and read its contents. -
    • urllistdir: List a directory, return an array of URLStat (file and ftp - schema supported). -
    • urlencode, urldecode: Encode and decode the URL. The above functions - expect a decoded URL. -
    - -
  • D Win32 COM libraries. - -
  • Sam McCall's class-based string library and - documentation. - -
  • DFL D Forms Library - -
  • Indigo - container classes -
- -

Games

- - - -

Media

- - - -

Comparisons and Benchmarks

- - - -

Miscellaneous

- - - -

Japanese Language

- - - - -

Images

- -Cut & paste the following free images on your web pages of interest to - D programmers: -

- - by Manfred Nowak - D-Man - by Christopher Sauls -
- by David L. 'SpottedTiger' Davis - by David L. 'SpottedTiger' Davis -
- by Greg Peet - by Greg Peet - by Greg Peet - The D Programming Language - by Greg Peet - by Greg Peet - by Manfred Nowak -

- - Corto's - D button images: - D Language - -

Submissions

- - If you have any D code, documents, - images or web pages of interest to D - programmers, - please - email - the links to Digital Mars. -

- -

-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - - - - + + + + + + + + +Digital Mars - The D Programming Language + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Sat Oct 8 22:10:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ + · Overview
+ + + · D for Win32
+ + + · Win32 DLLs in D
+ + + · C .h to D Modules
+ + + · FAQ
+ + + · Style Guide
+ + + · Example: wc
+ + + · Future
+ + + · D Change Log
+ + + · Tech Tips
+ + + · Rationale
+ + + · Glossary
+ + + · Acknowledgements
+ + +
+ Tools +
+ · DMD D Compiler
+ + + · GDC D Compiler
+ + + · Linker
+ + + · Profiler
+ + +
+ Community +
+ · News Digest
+ + + · News
+ + + · Forum
+ + + · Announcements
+ + + · Learn
+ + + · D links
+ + +
+ Archives +
+ · digitalmars.D
+ + + · digitalmars.D.dtl
+ + + · digitalmars.D.announce
+ + + · digitalmars.D.learn
+ + + · digitalmars.D.bugs
+ + + · D.gnu
+ + + · Old D
+ + +
+
+
+ +

D + Links

+ +

Wikis

+ + + +

Tools

+ +
    +
  • D-mode + an emacs mode for D + +
  • + DMD Front End Starter Kit + +
  • akIDE + is an open source IDE written in D. Comes with D syntax colouring, D + project wizard and DMD compiler support. + +
  • Andy Friesen has taken + SWIG + and + modified it to generate code for D. + +
  • + Zeus for Windows + comes with D compiler (*) and keywords predefined and + has a ctags program (xtags.exe) that supports the D language. + (*) For the D compiler to work within Zeus the user will need + to download and install the compiler from www.digitalmars.com/d/. If + it is already installed it should be automatic. + +
  • Program editors + customized for use with D +. + +
  • Build + tool for building D executables and libraries. + +
  • DStress + language conformance test suite. +
+ +

Libraries

+ +
    +
  • MinTL + a container library + +
  • Locks + a concurrent programming library + +
  • MinWin + a GUI toolkit + +
  • gmp-d + a D interface for GMP multi-precision float and big-integer library + +
  • SynSoft's D Page provides + a number of free D libraries. SynSoft is an imprint of + Synesis Software, + which provides free D, + Java, .NET, Perl and Python libraries. SynSoft has contributed several + modules to the D standard library, and is currently working on a + standard template library - the DTL. + +
  • Mango + for server side programming. + +
  • D MySQL Binding for Linux. + +
  • + D graphical User Interface (DUI) toolkit. + +
  • Simple URL loading + library by Burton Radons. + Requires the DIG library + to be installed, although it doesn't use it, just digc. + Comes with documentation. + It has the functions: +
      +
    • urlopen: Open a URL as a stream (http, file, and ftp schema supported). +
    • urlread: Open a URL and read its contents. +
    • urllistdir: List a directory, return an array of URLStat (file and ftp + schema supported). +
    • urlencode, urldecode: Encode and decode the URL. The above functions + expect a decoded URL. +
    + +
  • D Win32 COM libraries. + +
  • Sam McCall's class-based string library and + documentation. + +
  • DFL D Forms Library + +
  • Indigo + container classes +
+ +

Games

+ + + +

Media

+ + + +

Comparisons and Benchmarks

+ + + +

Miscellaneous

+ + + +

Japanese Language

+ + + + +

Images

+ +Cut & paste the following free images on your web pages of interest to + D + programmers: +

+ + by Manfred Nowak + D-Man + by Christopher Sauls +
+ by David L. 'SpottedTiger' Davis + by David L. 'SpottedTiger' Davis +
+ by Greg Peet + by Greg Peet + by Greg Peet + The D Programming Language + by Greg Peet + by Greg Peet + by Manfred Nowak +

+ + Corto's + D + button images: + D Language + +

Submissions

+ + If you have any D + code, documents, + images or web pages of interest to D + + programmers, + please + email + the links to Digital Mars. + + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/dll.html dmd-0.136/dmd/html/d/dll.html --- dmd-0.135/dmd/html/d/dll.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/dll.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,760 +1,814 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Writing Win32 DLLs - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - - -

Writing Win32 DLLs in D

- - DLLs (Dynamic Link Libraries) are one of the foundations - of system programming for Windows. The D programming - language enables the creation of several different types of - DLLs. -

- - For background information on what DLLs are and how they work - Chapter 11 of Jeffrey Richter's book - - Advanced Windows is indispensible. -

- - This guide will show how to create DLLs of various types with D. - -

- -

DLLs with a C Interface

- - A DLL presenting a C interface can connect to any other code - in a language that supports calling C functions in a DLL. - - DLLs can be created in D in roughly the same way as in C. - A DllMain() - is required, looking like: - -
-import std.c.windows.windows;
-HINSTANCE g_hInst;
-
-extern (C)
-{
-	void gc_init();
-	void gc_term();
-	void _minit();
-	void _moduleCtor();
-	void _moduleUnitTests();
-}
-
-extern (Windows)
-BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
-{
-    switch (ulReason)
-    {
-	case DLL_PROCESS_ATTACH:
-	    gc_init();			// initialize GC
-	    _minit();			// initialize module list
-	    _moduleCtor();		// run module constructors
-	    _moduleUnitTests();		// run module unit tests
-	    break;
-
-	case DLL_PROCESS_DETACH:
-	    gc_term();			// shut down GC
-	    break;
-
-	case DLL_THREAD_ATTACH:
-	case DLL_THREAD_DETACH:
-	    // Multiple threads not supported yet
-	    return false;
-    }
-    g_hInst=hInstance;
-    return true;
-}
-	
- - Notes: -
    -
  • The _moduleUnitTests() call is optional. -
  • The presence of DllMain() is recognized by the compiler - causing it to emit a reference to - __acrtused_dll - and the phobos.lib runtime library. -
- - Link with a .def - (Module Definition File) - along the lines of: - -
-	LIBRARY         MYDLL
-	DESCRIPTION     'My DLL written in D'
-
-	EXETYPE		NT
-	CODE            PRELOAD DISCARDABLE
-	DATA            PRELOAD SINGLE
-
-	EXPORTS
-			DllGetClassObject       @2
-			DllCanUnloadNow         @3
-			DllRegisterServer       @4
-			DllUnregisterServer     @5
-	
- - The functions in the EXPORTS list are for illustration. - Replace them with the actual exported functions from MYDLL. - Alternatively, use implib. - Here's an example of a simple DLL with a function print() - which prints a string: - -

mydll2.d:

-
-module mydll;
-export void dllprint() { printf("hello dll world\n"); }
-	
- -

mydll.def:

-
-LIBRARY "mydll.dll"
-EXETYPE NT
-SUBSYSTEM WINDOWS
-CODE SHARED EXECUTE
-DATA WRITE
-	
- - Put the code above that contains DllMain() into a file dll.d. - Compile and link the dll with the following command: - -
-dmd -ofmydll.dll mydll2.d dll.d mydll.def
-implib/system mydll.lib mydll.dll
-	
- - which will create mydll.dll and mydll.lib. - Now for a program, test.d, which will use the dll: - -

test.d:

-
-import mydll;
-
-int main()
-{
-   mydll.dllprint();
-   return 0;
-}
-	
- - Create a clone of mydll2.d that doesn't have the function bodies: - -

mydll.d:

-
-export void dllprint();
-	
- - Compile and link with the command: -
-dmd test.d mydll.lib
-	
- - and run: -
-C:>test
-hello dll world
-C:>
-	
- - - -

Memory Allocation

- - D DLLs use garbage collected memory management. The question is what - happens when pointers to allocated data cross DLL boundaries? - If the DLL presents a C interface, one would assume the reason - for that is to connect with code written in other languages. - Those other languages will not know anything about D's memory - management. Thus, the C interface will have to shield the - DLL's callers from needing to know anything about it. -

- - There are many approaches to solving this problem: - -

    - -
  • Do not return pointers to D gc allocated memory to the caller of - the DLL. Instead, have the caller allocate a buffer, and have the DLL - fill in that buffer. - -
  • Retain a pointer to the data within the D DLL so the GC will not free - it. Establish a protocol where the caller informs the D DLL when it is - safe to free the data. - -
  • Use operating system primitives like VirtualAlloc() to allocate - memory to be transferred between DLLs. - -
  • Use std.c.stdlib.malloc() (or another non-gc allocator) when - allocating data to be returned to the caller. Export a function - that will be used by the caller to free the data. - -
- -

COM Programming

- - Many Windows API interfaces are in terms of COM (Common Object Model) - objects (also called OLE or ActiveX objects). A COM object is an object - who's first field is a pointer to a vtbl[], and the first 3 entries - in that vtbl[] are for QueryInterface(), AddRef(), and Release(). -

- - For understanding COM, Kraig Brockshmidt's - - Inside OLE - is an indispensible resource. -

- - COM objects are analogous to D interfaces. Any COM object can be - expressed as a D interface, and every D object with an interface X - can be exposed as a COM object X. - This means that D is compatible with COM objects implemented - in other languages. -

- - While not strictly necessary, the Phobos library provides an Object - useful as a super class for all D COM objects, called ComObject. - ComObject provides a default implementation for - QueryInterface(), AddRef(), and Release(). -

- - Windows COM objects use the Windows calling convention, which is not - the default for D, so COM functions need to have the attribute - extern (Windows). - - So, to write a COM object: - -

-import std.c.windows.com;
-
-class MyCOMobject : ComObject
-{
-    extern (Windows):
-	...
-}
-	
- - The sample code includes an example COM client program and server DLL. - -

D code calling D code in DLLs

- - Having DLLs in D be able to talk to each other as if they - were statically linked together is, of course, very desirable - as code between applications can be shared, and different - DLLs can be independently developed. -

- - The underlying difficulty is what to do about garbage collection (gc). - Each EXE and DLL will have their own gc instance. While - these gc's can coexist without stepping on each other, - it's redundant and inefficient to have multiple gc's running. - The idea explored here is to pick one gc and have the DLLs - redirect their gc's to use that one. The one gc used here will be - the one in the EXE file, although it's also possible to make a - separate DLL just for the gc. -

- - The example will show both how to statically load a DLL, and - to dynamically load/unload it. -

- - Starting with the code for the DLL, mydll.d: -

-/*
- * MyDll demonstration of how to write D DLLs.
- */
-
-import std.c.stdio;
-import std.c.stdlib;
-import std.string;
-import std.c.windows.windows;
-import std.gc;
-
-HINSTANCE   g_hInst;
-
-extern (C)
-{
-	void _minit();
-	void _moduleCtor();
-	void _moduleDtor();
-	void _moduleUnitTests();
-}
-
-extern (Windows)
-    BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
-{
-    switch (ulReason)
-    {
-        case DLL_PROCESS_ATTACH:
-	    printf("DLL_PROCESS_ATTACH\n");
-	    break;
-
-        case DLL_PROCESS_DETACH:
-	    printf("DLL_PROCESS_DETACH\n");
-	    std.c.stdio._fcloseallp = null; // so stdio doesn't get closed
-	    break;
-
-        case DLL_THREAD_ATTACH:
-	    printf("DLL_THREAD_ATTACH\n");
-	    return false;
-
-        case DLL_THREAD_DETACH:
-	    printf("DLL_THREAD_DETACH\n");
-	    return false;
-    }
-    g_hInst = hInstance;
-    return true;
-}
-
-export void MyDLL_Initialize(void* gc)
-{
-    printf("MyDLL_Initialize()\n");
-    std.gc.setGCHandle(gc);
-    _minit();
-    _moduleCtor();
-//  _moduleUnitTests();
-}
-
-export void MyDLL_Terminate()
-{
-    printf("MyDLL_Terminate()\n");
-    _moduleDtor();			// run module destructors
-    std.gc.endGCHandle();
-}
-
-static this()
-{
-    printf("static this for mydll\n");
-}
-
-static ~this()
-{
-    printf("static ~this for mydll\n");
-}
-
-/* --------------------------------------------------------- */
-
-class MyClass
-{
-    char[] concat(char[] a, char[] b)
-    {
-	return a ~ " " ~ b;
-    }
-
-    void free(char[] s)
-    {
-	delete s;
-    }
-}
-
-export MyClass getMyClass()
-{
-    return new MyClass();
-}
-	
- -
-
DllMain -
This is the main entry point for any D DLL. It gets called - by the C startup code - (for DMC++, the source is \dm\src\win32\dllstart.c). - The printf's are placed there so one can trace how it gets - called. - Notice that the initialization and termination code seen in - the earlier DllMain sample code isn't there. - This is because the initialization will depend on who is loading - the DLL, and how it is loaded (statically or dynamically). - There isn't much to do here. - The only oddity is the setting of std.d.stdio._fcloseallp to - null. If this is not set to null, the C runtime will flush - and close all the standard I/O buffers (like stdout, - stderr, etc.) - shutting off further output. Setting it to null defers the - responsibility for that to the caller of the DLL. -

- -

MyDLL_Initialize -
So instead we'll have our own DLL initialization routine so - exactly when it is called can be controlled. - It must be called after the caller has initialized itself, - the Phobos runtime library, and the module constructors - (this would normally be by the time main() was entered). - This function takes one argument, a handle to the - caller's gc. We'll see how that handle is obtained later. - Instead of gc_init() being called to initialize - the DLL's gc, std.gc.setGCHandle() is called and passed the - handle to which gc to use. - This step informs the caller's gc - which data areas of the DLL to scan. - Afterwards follows the call to the _minit() to initialize the - module tables, and _moduleCtor() to run the module constructors. - _moduleUnitTests() is optional and runs the DLL's unit tests. - The function is exported as that is how a function is made - visible outside of a DLL. -

- -

MyDLL_Terminate -
Correspondingly, this function terminates the DLL, and is - called prior to unloading it. - It has two jobs; calling the DLL's module destructors via - _moduleDtor() and informing the runtime that - the DLL will no longer be using the caller's gc via - std.gc.endGCHandle(). - That last step is critical, as the DLL will be unmapped from - memory, and if the gc continues to scan its data areas it will - cause segment faults. -

- -

static this, static ~this -
These are examples of the module's static constructor - and destructor, - here with a print in each to verify that they are running - and when. -

- -

MyClass -
This is an example of a class that can be exported from - and used by the caller of a DLL. The concat member - function allocates some gc memory, and free frees gc - memory. -

- -

getMyClass -
An exported factory that allocates an instance of MyClass - and returns a reference to it. -

- -

- - To build the mydll.dll DLL: - -
    -
  1. dmd -c mydll -g -
    Compiles mydll.d into mydll.obj. - -g turns on debug info generation. -

    - -

  2. dmd mydll.obj \dmd\lib\gcstub.obj mydll.def -g -L/map -
    Links mydll.obj into a DLL named mydll.dll. - gcstub.obj is not required, but it prevents the bulk - of the gc code from being linked in, since it will not be used - anyway. It saves about 12Kb. - mydll.def is the - Module Definition File, - and has the contents: -
    -	LIBRARY         MYDLL
    -	DESCRIPTION     'MyDll demonstration DLL'
    -	EXETYPE		NT
    -	CODE            PRELOAD DISCARDABLE
    -	DATA            PRELOAD SINGLE
    - -g turns on debug info generation, and - -L/map generates a map file mydll.map. -

    - -

  3. implib /noi /system mydll.lib mydll.dll -
    Creates an - import library - mydll.lib suitable - for linking in with an application that will be statically - loading mydll.dll. -

    - -

- - Here's test.d, a sample application that makes use of - mydll.dll. There are two versions, one statically binds to - the DLL, and the other dynamically loads it. - -
-import std.stdio;
-import std.gc;
-
-import mydll;
-
-//version=DYNAMIC_LOAD;
-
-version (DYNAMIC_LOAD)
-{
-    import std.c.windows.windows;
-
-    alias void function(void*) MyDLL_Initialize_fp;
-    alias void function() MyDLL_Terminate_fp;
-    alias MyClass function() getMyClass_fp;
-
-    int main()
-    {	HMODULE h;
-	FARPROC fp;
-	MyDLL_Initialize_fp mydll_initialize;
-	MyDLL_Terminate_fp  mydll_terminate;
-
-	getMyClass_fp  getMyClass;
-	MyClass c;
-
-	printf("Start Dynamic Link...\n");
-
-	h = LoadLibraryA("mydll.dll");
-	if (h == null)
-	{   printf("error loading mydll.dll\n");
-	    return 1;
-	}
-
-	fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv");
-	if (fp == null)
-	{   printf("error loading symbol MyDLL_Initialize()\n");
-	    return 1;
-	}
-
-	mydll_initialize = cast(MyDLL_Initialize_fp) fp;
-	(*mydll_initialize)(std.gc.getGCHandle());
-
-	fp = GetProcAddress(h, "D5mydll10getMyClassFZC5mydll7MyClass");
-	if (fp == null)
-	{   printf("error loading symbol getMyClass()\n");
-	    return 1;
-	}
-
-	getMyClass = cast(getMyClass_fp) fp;
-	c = (*getMyClass)();
-	foo(c);
-
-	fp = GetProcAddress(h, "D5mydll15MyDLL_TerminateFZv");
-	if (fp == null)
-	{   printf("error loading symbol MyDLL_Terminate()\n");
-	    return 1;
-	}
-
-	mydll_terminate = cast(MyDLL_Terminate_fp) fp;
-	(*mydll_terminate)();
-
-	if (FreeLibrary(h) == FALSE)
-	{   printf("error freeing mydll.dll\n");
-	    return 1;
-	}
-
-	printf("End...\n");
-	return 0;
-    }
-}
-else
-{   // static link the DLL
-
-    int main()
-    {
-	printf("Start Static Link...\n");
-	MyDLL_Initialize(std.gc.getGCHandle());
-	foo(getMyClass());
-	MyDLL_Terminate();
-	printf("End...\n");
-	return 0;
-    }
-}
-
-void foo(MyClass c)
-{
-    char[] s;
-
-    s = c.concat("Hello", "world!");
-    writefln(s);
-    c.free(s);
-    delete c;
-}
-	
- - Let's start with the statically linked version, which is simpler. - It's compiled and linked with the command: -
dmd test mydll.lib -g
- Note how it is linked with mydll.lib, the import library - for mydll.dll. - The code is straightforward, it initializes mydll.lib with - a call to MyDLL_Initialize(), passing the handle - to test.exe's gc. - Then, we can use the DLL and call its functions just as if - it were part of test.exe. In foo(), gc memory - is allocated and freed both by test.exe and mydll.dll. - When we're done using the DLL, it is terminated with - MyDLL_Terminate(). -

- - Running it looks like this: -

-DLL_PROCESS_ATTACH
-Start Static Link...
-MyDLL_Initialize()
-static this for mydll
-Hello world!
-MyDLL_Terminate()
-static ~this for mydll
-End...
- - The dynamically linked version is a little harder to set up. - Compile and link it with the command: -
dmd test -version=DYNAMIC_LOAD -g
- The import library mydll.lib is not needed. - The DLL is loaded with a call to - LoadLibraryA(), - and each exported function has to be retrieved via - a call to - GetProcAddress(). - An easy way to get the decorated name to pass to GetProcAddress() - is to copy and paste it from the generated mydll.map file - under the Export heading. - Once this is done, we can use the member functions of the - DLL classes as if they were part of test.exe. - When done, release the DLL with - FreeLibrary(). -

- - Running it looks like this: -

-Start Dynamic Link...
-DLL_PROCESS_ATTACH
-MyDLL_Initialize()
-static this for mydll
-Hello world!
-MyDLL_Terminate()
-static ~this for mydll
-DLL_PROCESS_DETACH
-End...
- -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Writing Win32 DLLs + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ + · Overview
+ + + · D for Win32
+ + + · Win32 DLLs in D
+ + + · C .h to D Modules
+ + + · FAQ
+ + + · Style Guide
+ + + · Example: wc
+ + + · Future
+ + + · D Change Log
+ + + · Tech Tips
+ + + · Rationale
+ + + · Glossary
+ + + · Acknowledgements
+ + +
+ Tools +
+ · DMD D Compiler
+ + + · GDC D Compiler
+ + + · Linker
+ + + · Profiler
+ + +
+ Community +
+ · News Digest
+ + + · News
+ + + · Forum
+ + + · Announcements
+ + + · Learn
+ + + · D links
+ + +
+ Archives +
+ · digitalmars.D
+ + + · digitalmars.D.dtl
+ + + · digitalmars.D.announce
+ + + · digitalmars.D.learn
+ + + · digitalmars.D.bugs
+ + + · D.gnu
+ + + · Old D
+ + +
+
+
+ + +

Writing Win32 DLLs in D

+ + DLLs (Dynamic Link Libraries) are one of the foundations + of system programming for Windows. The D programming + language enables the creation of several different types of + DLLs. +

+ + For background information on what DLLs are and how they work + Chapter 11 of Jeffrey Richter's book + + Advanced Windows is indispensible. +

+ + This guide will show how to create DLLs of various types with D. + +

+ +

DLLs with a C Interface

+ + A DLL presenting a C interface can connect to any other code + in a language that supports calling C functions in a DLL. + + DLLs can be created in D in roughly the same way as in C. + A DllMain() + is required, looking like: + +
import std.c.windows.windows;
+HINSTANCE g_hInst;
+
+extern (C)
+{
+	void gc_init();
+	void gc_term();
+	void _minit();
+	void _moduleCtor();
+	void _moduleUnitTests();
+}
+
+extern (Windows)
+BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
+{
+    switch (ulReason)
+    {
+	case DLL_PROCESS_ATTACH:
+	    gc_init();			// initialize GC
+	    _minit();			// initialize module list
+	    _moduleCtor();		// run module constructors
+	    _moduleUnitTests();		// run module unit tests
+	    break;
+
+	case DLL_PROCESS_DETACH:
+	    gc_term();			// shut down GC
+	    break;
+
+	case DLL_THREAD_ATTACH:
+	case DLL_THREAD_DETACH:
+	    // Multiple threads not supported yet
+	    return false;
+    }
+    g_hInst=hInstance;
+    return true;
+}
+
+ + Notes: +
    +
  • The _moduleUnitTests() call is optional. +
  • The presence of DllMain() is recognized by the compiler + causing it to emit a reference to + __acrtused_dll + and the phobos.lib runtime library. +
+ + Link with a .def + (Module Definition File) + along the lines of: + +
LIBRARY         MYDLL
+DESCRIPTION     'My DLL written in D'
+
+EXETYPE		NT
+CODE            PRELOAD DISCARDABLE
+DATA            PRELOAD SINGLE
+
+EXPORTS
+		DllGetClassObject       @2
+		DllCanUnloadNow         @3
+		DllRegisterServer       @4
+		DllUnregisterServer     @5
+
+ + + The functions in the EXPORTS list are for illustration. + Replace them with the actual exported functions from MYDLL. + Alternatively, use implib. + Here's an example of a simple DLL with a function print() + which prints a string: + +

mydll2.d:

+
module mydll;
+export void dllprint() { printf("hello dll world\n"); }
+
+ +

mydll.def:

+ +
LIBRARY "mydll.dll"
+EXETYPE NT
+SUBSYSTEM WINDOWS
+CODE SHARED EXECUTE
+DATA WRITE
+
+ + + Put the code above that contains DllMain() into a file dll.d. + Compile and link the dll with the following command: + +
C:>dmd -ofmydll.dll mydll2.d dll.d mydll.def
+C:>implib/system mydll.lib mydll.dll
+C:>
+
+ + which will create mydll.dll and mydll.lib. + Now for a program, test.d, which will use the dll: + +

test.d:

+
import mydll;
+
+int main()
+{
+   mydll.dllprint();
+   return 0;
+}
+
+ + Create a clone of mydll2.d that doesn't have the function bodies: + +

mydll.d:

+
export void dllprint();
+
+ + Compile and link with the command: + +
C:>dmd test.d mydll.lib
+C:>
+
+ + and run: +
C:>test
+hello dll world
+C:>
+
+ + + +

Memory Allocation

+ + D DLLs use garbage collected memory management. The question is what + happens when pointers to allocated data cross DLL boundaries? + If the DLL presents a C interface, one would assume the reason + for that is to connect with code written in other languages. + Those other languages will not know anything about D's memory + management. Thus, the C interface will have to shield the + DLL's callers from needing to know anything about it. +

+ + There are many approaches to solving this problem: + +

    + +
  • Do not return pointers to D gc allocated memory to the caller of + the DLL. Instead, have the caller allocate a buffer, and have the DLL + fill in that buffer. + +
  • Retain a pointer to the data within the D DLL so the GC will not free + it. Establish a protocol where the caller informs the D DLL when it is + safe to free the data. + +
  • Use operating system primitives like VirtualAlloc() to allocate + memory to be transferred between DLLs. + +
  • Use std.c.stdlib.malloc() (or another non-gc allocator) when + allocating data to be returned to the caller. Export a function + that will be used by the caller to free the data. + +
+ +

COM Programming

+ + Many Windows API interfaces are in terms of COM (Common Object Model) + objects (also called OLE or ActiveX objects). A COM object is an object + who's first field is a pointer to a vtbl[], and the first 3 entries + in that vtbl[] are for QueryInterface(), AddRef(), and Release(). +

+ + For understanding COM, Kraig Brockshmidt's + + Inside OLE + is an indispensible resource. +

+ + COM objects are analogous to D interfaces. Any COM object can be + expressed as a D interface, and every D object with an interface X + can be exposed as a COM object X. + This means that D is compatible with COM objects implemented + in other languages. +

+ + While not strictly necessary, the Phobos library provides an Object + useful as a super class for all D COM objects, called ComObject. + ComObject provides a default implementation for + QueryInterface(), AddRef(), and Release(). +

+ + Windows COM objects use the Windows calling convention, which is not + the default for D, so COM functions need to have the attribute + extern (Windows). + + So, to write a COM object: + +

import std.c.windows.com;
+
+class MyCOMobject : ComObject
+{
+    extern (Windows):
+	...
+}
+
+ + The sample code includes an example COM client program and server DLL. + +

D code calling D code in DLLs

+ + Having DLLs in D be able to talk to each other as if they + were statically linked together is, of course, very desirable + as code between applications can be shared, and different + DLLs can be independently developed. +

+ + The underlying difficulty is what to do about garbage collection (gc). + Each EXE and DLL will have their own gc instance. While + these gc's can coexist without stepping on each other, + it's redundant and inefficient to have multiple gc's running. + The idea explored here is to pick one gc and have the DLLs + redirect their gc's to use that one. The one gc used here will be + the one in the EXE file, although it's also possible to make a + separate DLL just for the gc. +

+ + The example will show both how to statically load a DLL, and + to dynamically load/unload it. +

+ + Starting with the code for the DLL, mydll.d: +

/*
+ * MyDll demonstration of how to write D DLLs.
+ */
+
+import std.c.stdio;
+import std.c.stdlib;
+import std.string;
+import std.c.windows.windows;
+import std.gc;
+
+HINSTANCE   g_hInst;
+
+extern (C)
+{
+	void _minit();
+	void _moduleCtor();
+	void _moduleDtor();
+	void _moduleUnitTests();
+}
+
+extern (Windows)
+    BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
+{
+    switch (ulReason)
+    {
+        case DLL_PROCESS_ATTACH:
+	    printf("DLL_PROCESS_ATTACH\n");
+	    break;
+
+        case DLL_PROCESS_DETACH:
+	    printf("DLL_PROCESS_DETACH\n");
+	    std.c.stdio._fcloseallp = null; // so stdio doesn't get closed
+	    break;
+
+        case DLL_THREAD_ATTACH:
+	    printf("DLL_THREAD_ATTACH\n");
+	    return false;
+
+        case DLL_THREAD_DETACH:
+	    printf("DLL_THREAD_DETACH\n");
+	    return false;
+    }
+    g_hInst = hInstance;
+    return true;
+}
+
+export void MyDLL_Initialize(void* gc)
+{
+    printf("MyDLL_Initialize()\n");
+    std.gc.setGCHandle(gc);
+    _minit();
+    _moduleCtor();
+//  _moduleUnitTests();
+}
+
+export void MyDLL_Terminate()
+{
+    printf("MyDLL_Terminate()\n");
+    _moduleDtor();			// run module destructors
+    std.gc.endGCHandle();
+}
+
+static this()
+{
+    printf("static this for mydll\n");
+}
+
+static ~this()
+{
+    printf("static ~this for mydll\n");
+}
+
+/* --------------------------------------------------------- */
+
+class MyClass
+{
+    char[] concat(char[] a, char[] b)
+    {
+	return a ~ " " ~ b;
+    }
+
+    void free(char[] s)
+    {
+	delete s;
+    }
+}
+
+export MyClass getMyClass()
+{
+    return new MyClass();
+}
+
+ +
+
DllMain +
This is the main entry point for any D DLL. It gets called + by the C startup code + (for DMC++, the source is \dm\src\win32\dllstart.c). + The printf's are placed there so one can trace how it gets + called. + Notice that the initialization and termination code seen in + the earlier DllMain sample code isn't there. + This is because the initialization will depend on who is loading + the DLL, and how it is loaded (statically or dynamically). + There isn't much to do here. + The only oddity is the setting of std.d.stdio._fcloseallp to + null. If this is not set to null, the C runtime will flush + and close all the standard I/O buffers (like stdout, + stderr, etc.) + shutting off further output. Setting it to null defers the + responsibility for that to the caller of the DLL. +

+ +

MyDLL_Initialize +
So instead we'll have our own DLL initialization routine so + exactly when it is called can be controlled. + It must be called after the caller has initialized itself, + the Phobos runtime library, and the module constructors + (this would normally be by the time main() was entered). + This function takes one argument, a handle to the + caller's gc. We'll see how that handle is obtained later. + Instead of gc_init() being called to initialize + the DLL's gc, std.gc.setGCHandle() is called and passed the + handle to which gc to use. + This step informs the caller's gc + which data areas of the DLL to scan. + Afterwards follows the call to the _minit() to initialize the + module tables, and _moduleCtor() to run the module constructors. + _moduleUnitTests() is optional and runs the DLL's unit tests. + The function is exported as that is how a function is made + visible outside of a DLL. +

+ +

MyDLL_Terminate +
Correspondingly, this function terminates the DLL, and is + called prior to unloading it. + It has two jobs; calling the DLL's module destructors via + _moduleDtor() and informing the runtime that + the DLL will no longer be using the caller's gc via + std.gc.endGCHandle(). + That last step is critical, as the DLL will be unmapped from + memory, and if the gc continues to scan its data areas it will + cause segment faults. +

+ +

static this, static ~this +
These are examples of the module's static constructor + and destructor, + here with a print in each to verify that they are running + and when. +

+ +

MyClass +
This is an example of a class that can be exported from + and used by the caller of a DLL. The concat member + function allocates some gc memory, and free frees gc + memory. +

+ +

getMyClass +
An exported factory that allocates an instance of MyClass + and returns a reference to it. +

+ +

+ + To build the mydll.dll DLL: + +
    +
  1. dmd -c mydll -g +
    Compiles mydll.d into mydll.obj. + -g turns on debug info generation. +

    + +

  2. dmd mydll.obj \dmd\lib\gcstub.obj mydll.def -g -L/map +
    Links mydll.obj into a DLL named mydll.dll. + gcstub.obj is not required, but it prevents the bulk + of the gc code from being linked in, since it will not be used + anyway. It saves about 12Kb. + mydll.def is the + Module Definition File, + and has the contents: + +
    LIBRARY         MYDLL
    +DESCRIPTION     'MyDll demonstration DLL'
    +EXETYPE		NT
    +CODE            PRELOAD DISCARDABLE
    +DATA            PRELOAD SINGLE
    +
    + + -g turns on debug info generation, and + -L/map generates a map file mydll.map. +

    + +

  3. implib /noi /system mydll.lib mydll.dll +
    Creates an + import library + mydll.lib suitable + for linking in with an application that will be statically + loading mydll.dll. +

    + +

+ + Here's test.d, a sample application that makes use of + mydll.dll. There are two versions, one statically binds to + the DLL, and the other dynamically loads it. + +
import std.stdio;
+import std.gc;
+
+import mydll;
+
+//version=DYNAMIC_LOAD;
+
+version (DYNAMIC_LOAD)
+{
+    import std.c.windows.windows;
+
+    alias void function(void*) MyDLL_Initialize_fp;
+    alias void function() MyDLL_Terminate_fp;
+    alias MyClass function() getMyClass_fp;
+
+    int main()
+    {	HMODULE h;
+	FARPROC fp;
+	MyDLL_Initialize_fp mydll_initialize;
+	MyDLL_Terminate_fp  mydll_terminate;
+
+	getMyClass_fp  getMyClass;
+	MyClass c;
+
+	printf("Start Dynamic Link...\n");
+
+	h = LoadLibraryA("mydll.dll");
+	if (h == null)
+	{   printf("error loading mydll.dll\n");
+	    return 1;
+	}
+
+	fp = GetProcAddress(h, "D5mydll16MyDLL_InitializeFPvZv");
+	if (fp == null)
+	{   printf("error loading symbol MyDLL_Initialize()\n");
+	    return 1;
+	}
+
+	mydll_initialize = cast(MyDLL_Initialize_fp) fp;
+	(*mydll_initialize)(std.gc.getGCHandle());
+
+	fp = GetProcAddress(h, "D5mydll10getMyClassFZC5mydll7MyClass");
+	if (fp == null)
+	{   printf("error loading symbol getMyClass()\n");
+	    return 1;
+	}
+
+	getMyClass = cast(getMyClass_fp) fp;
+	c = (*getMyClass)();
+	foo(c);
+
+	fp = GetProcAddress(h, "D5mydll15MyDLL_TerminateFZv");
+	if (fp == null)
+	{   printf("error loading symbol MyDLL_Terminate()\n");
+	    return 1;
+	}
+
+	mydll_terminate = cast(MyDLL_Terminate_fp) fp;
+	(*mydll_terminate)();
+
+	if (FreeLibrary(h) == FALSE)
+	{   printf("error freeing mydll.dll\n");
+	    return 1;
+	}
+
+	printf("End...\n");
+	return 0;
+    }
+}
+else
+{   // static link the DLL
+
+    int main()
+    {
+	printf("Start Static Link...\n");
+	MyDLL_Initialize(std.gc.getGCHandle());
+	foo(getMyClass());
+	MyDLL_Terminate();
+	printf("End...\n");
+	return 0;
+    }
+}
+
+void foo(MyClass c)
+{
+    char[] s;
+
+    s = c.concat("Hello", "world!");
+    writefln(s);
+    c.free(s);
+    delete c;
+}
+
+ + Let's start with the statically linked version, which is simpler. + It's compiled and linked with the command: + +
C:>dmd test mydll.lib -g
+
+ + Note how it is linked with mydll.lib, the import library + for mydll.dll. + The code is straightforward, it initializes mydll.lib with + a call to MyDLL_Initialize(), passing the handle + to test.exe's gc. + Then, we can use the DLL and call its functions just as if + it were part of test.exe. In foo(), gc memory + is allocated and freed both by test.exe and mydll.dll. + When we're done using the DLL, it is terminated with + MyDLL_Terminate(). +

+ + Running it looks like this: + +

C:>test
+DLL_PROCESS_ATTACH
+Start Static Link...
+MyDLL_Initialize()
+static this for mydll
+Hello world!
+MyDLL_Terminate()
+static ~this for mydll
+End...
+C:>
+
+ + The dynamically linked version is a little harder to set up. + Compile and link it with the command: + +
C:>dmd test -version=DYNAMIC_LOAD -g
+
+ The import library mydll.lib is not needed. + The DLL is loaded with a call to + LoadLibraryA(), + and each exported function has to be retrieved via + a call to + GetProcAddress(). + An easy way to get the decorated name to pass to GetProcAddress() + is to copy and paste it from the generated mydll.map file + under the Export heading. + Once this is done, we can use the member functions of the + DLL classes as if they were part of test.exe. + When done, release the DLL with + FreeLibrary(). +

+ + Running it looks like this: +

C:>test
+Start Dynamic Link...
+DLL_PROCESS_ATTACH
+MyDLL_Initialize()
+static this for mydll
+Hello world!
+MyDLL_Terminate()
+static ~this for mydll
+DLL_PROCESS_DETACH
+End...
+C:>
+
+ + +
+ + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/dstyle.html dmd-0.136/dmd/html/d/dstyle.html --- dmd-0.135/dmd/html/d/dstyle.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/dstyle.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,290 +1,329 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - The D Style - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
- - · Overview
- · D for Win32
- · Win32 DLLs in D
- · C .h to D Modules
- · FAQ
- · Style Guide
- · Example: wc
- · Future
- · D Change Log
- · Tech Tips
- · Glossary
- · Acknowledgements
-
- Tools -
- · DMD D Compiler
- · GDC D Compiler
- · Linker
- · Profiler
-
- Community -
- · News Digest
- · News
- · Forum
- · Announcements
- · Learn
- · D links
-
- Archives -
- · digitalmars.D
- · digitalmars.D.dtl
- · digitalmars.D.announce
- · digitalmars.D.learn
- · digitalmars.D.bugs
- · D.gnu
- · Old D
-
-
-
- - - -

The D Style

- - The D Style is a set of style conventions for writing - D programs. The D Style is not enforced by the compiler, it is - purely cosmetic and a matter of choice. Adhering to the D Style, - however, will make it easier for others to work with your D - code and easier for you to work with others' D code. - The D Style can form the starting point for a D project - style guide customized for your project team. - -

White Space

- -
    -
  • One statement per line. - -
  • Two or more spaces per indentation level. - -
  • Operators are separated by single spaces from their operands. - -
  • Two blank lines separating function bodies. - -
  • One blank line separating variable declarations from statements - in function bodies. -
- -

Comments

- -
    -
  • Use // comments to document a single line: -
    -	    statement;	// comment
    -	    statement;	// comment
    -	
    - -
  • Use block comments to document a multiple line block of - statements: -
    -	    /*
    -	     * comment
    -	     * comment
    -	     */
    -	     statement;
    -	     statement;
    -	
    - -
  • Use nesting comments to 'comment out' a piece of trial code: -
    -	/+++++
    -	    /*
    -	     * comment
    -	     * comment
    -	     */
    -	     statement;
    -	     statement;
    -	 +++++/
    -	
    - -
- -

Naming Conventions

- -
-
General -
Names formed by joining multiple works should have each word - other than the first capitalized. - -
-	int myFunc();
-	
- -
Module
-
Module names are all lower case. This avoids problems dealing - with case insensitive file systems. -

- -

C Modules
-
Modules that are interfaces to C functions go into the "c" - package, for example: -
-	import std.c.stdio;
-	
- Module names should be all lower case. -

- -

Class, Struct, Union, Enum names -
are capitalized. - -
-	class Foo;
-	class FooAndBar;
-	
- -
Function names -
Function names are not capitalized. - -
-	int done();
-	int doneProcessing();
-	
- -
Const names -
Are in all caps. - -
Enum member names -
Are in all caps. - -
- -

Meaningless Type Aliases

- - Things like: - -
-	alias void VOID;
-	alias int INT;
-	alias int* pint;
-	
- - should be avoided. - -

Declaration Style

- - Since in D the declarations are left-associative, left justify them: - -
-	int[] x, y;	// makes it clear that x and y are the same type
-	int** p, q;	// makes it clear that p and q are the same type
-	
- - to emphasize their relationship. Do not use the C style: - -
-	int []x, y;	// confusing since y is also an int[]
-	int **p, q;	// confusing since q is also an int**
-	
- -

Operator Overloading

- - Operator overloading is a powerful tool to extend the basic - types supported by the language. But being powerful, it has - great potential for creating obfuscated code. In particular, - the existing D operators have conventional meanings, such - as '+' means 'add' and '<<' means 'shift left'. - Overloading operator '+' with a meaning different from 'add' - is arbitrarily confusing and should be avoided. - -

Hungarian Notation

- - Just say no. - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - The D Style + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ + · Overview
+ + + · D for Win32
+ + + · Win32 DLLs in D
+ + + · C .h to D Modules
+ + + · FAQ
+ + + · Style Guide
+ + + · Example: wc
+ + + · Future
+ + + · D Change Log
+ + + · Tech Tips
+ + + · Rationale
+ + + · Glossary
+ + + · Acknowledgements
+ + +
+ Tools +
+ · DMD D Compiler
+ + + · GDC D Compiler
+ + + · Linker
+ + + · Profiler
+ + +
+ Community +
+ · News Digest
+ + + · News
+ + + · Forum
+ + + · Announcements
+ + + · Learn
+ + + · D links
+ + +
+ Archives +
+ · digitalmars.D
+ + + · digitalmars.D.dtl
+ + + · digitalmars.D.announce
+ + + · digitalmars.D.learn
+ + + · digitalmars.D.bugs
+ + + · D.gnu
+ + + · Old D
+ + +
+
+
+ + +

The D Style

+ + The D Style is a set of style conventions for writing + D programs. The D Style is not enforced by the compiler, it is + purely cosmetic and a matter of choice. Adhering to the D Style, + however, will make it easier for others to work with your D + code and easier for you to work with others' D code. + The D Style can form the starting point for a D project + style guide customized for your project team. + +

White Space

+ +
    +
  • One statement per line. + +
  • Two or more spaces per indentation level. + +
  • Operators are separated by single spaces from their operands. + +
  • Two blank lines separating function bodies. + +
  • One blank line separating variable declarations from statements + in function bodies. +
+ +

Comments

+ +
    +
  • Use // comments to document a single line: +
    statement;	// comment
    +statement;	// comment
    +
    + +
  • Use block comments to document a multiple line block of + statements: +
    /*
    + * comment
    + * comment
    + */
    + statement;
    + statement;
    +
    + +
  • Use nesting comments to 'comment out' a piece of trial code: +
    /+++++
    +    /*
    +     * comment
    +     * comment
    +     */
    +     statement;
    +     statement;
    + +++++/
    +
    + +
+ +

Naming Conventions

+ +
+
General +
Names formed by joining multiple works should have each word + other than the first capitalized. + +
int myFunc();
+
+ +
Module
+
Module names are all lower case. This avoids problems dealing + with case insensitive file systems. +

+ +

C Modules
+
Modules that are interfaces to C functions go into the "c" + package, for example: +
import std.c.stdio;
+
+ Module names should be all lower case. +

+ +

Class, Struct, Union, Enum names +
are capitalized. + +
class Foo;
+class FooAndBar;
+
+ +
Function names +
Function names are not capitalized. + +
int done();
+int doneProcessing();
+
+ +
Const names +
Are in all caps. + +
Enum member names +
Are in all caps. + +
+ +

Meaningless Type Aliases

+ + Things like: + +
alias void VOID;
+alias int INT;
+alias int* pint;
+
+ + should be avoided. + +

Declaration Style

+ + Since in D the declarations are left-associative, left justify them: + +
int[] x, y;	// makes it clear that x and y are the same type
+int** p, q;	// makes it clear that p and q are the same type
+
+ + to emphasize their relationship. Do not use the C style: + +
int []x, y;	// confusing since y is also an int[]
+int **p, q;	// confusing since q is also an int**
+
+ +

Operator Overloading

+ + Operator overloading is a powerful tool to extend the basic + types supported by the language. But being powerful, it has + great potential for creating obfuscated code. In particular, + the existing D operators have conventional meanings, such + as '+' means 'add' and '<<' means 'shift left'. + Overloading operator '+' with a meaning different from 'add' + is arbitrarily confusing and should be avoided. + +

Hungarian Notation

+ + Just say no. + + +
+ + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/entity.html dmd-0.136/dmd/html/d/entity.html --- dmd-0.135/dmd/html/d/entity.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/entity.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,410 +1,461 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Named Character Entities - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

Named Character Entities

- - These are the character entity names supported by D. -

- - Note: Not all will display properly in the Symbol - column in all browsers. -

- - - -

- -
Name Value Symbol - -
quot 34 " -
amp 38 & -
lt 60 < -
gt 62 > - -
OElig 338 Œ -
oelig 339 œ -
Scaron 352 Š -
scaron 353 š -
Yuml 376 Ÿ -
circ 710 ˆ -
tilde 732 ˜ -
ensp 8194   -
emsp 8195   -
thinsp 8201   -
zwnj 8204 ‌ -
zwj 8205 ‍ -
lrm 8206 ‎ -
rlm 8207 ‏ -
ndash 8211 – -
mdash 8212 — -
lsquo 8216 ‘ -
rsquo 8217 ’ -
sbquo 8218 ‚ -
ldquo 8220 “ -
rdquo 8221 ” -
bdquo 8222 „ -
dagger 8224 † -
Dagger 8225 ‡ -
permil 8240 ‰ -
lsaquo 8249 ‹ -
rsaquo 8250 › -
euro 8364 € - - - -
nbsp 160   -
iexcl 161 ¡ -
cent 162 ¢ -
pound 163 £ -
curren 164 ¤ -
yen 165 ¥ -
brvbar 166 ¦ -
sect 167 § -
uml 168 ¨ -
copy 169 © -
ordf 170 ª -
laquo 171 « -
not 172 ¬ -
shy 173 ­ -
reg 174 ® -
macr 175 ¯ -
deg 176 ° -
plusmn 177 ± -
sup2 178 ² -
sup3 179 ³ -
acute 180 ´ -
micro 181 µ -
para 182 ¶ -
middot 183 · -
cedil 184 ¸ -
sup1 185 ¹ -
ordm 186 º -
raquo 187 » -
frac14 188 ¼ -
frac12 189 ½ -
frac34 190 ¾ -
iquest 191 ¿ -
Agrave 192 À -
Aacute 193 Á -
Acirc 194 Â -
Atilde 195 Ã -
Auml 196 Ä -
Aring 197 Å -
AElig 198 Æ -
Ccedil 199 Ç -
Egrave 200 È -
Eacute 201 É -
Ecirc 202 Ê -
Euml 203 Ë -
Igrave 204 Ì -
Iacute 205 Í -
Icirc 206 Î -
Iuml 207 Ï -
ETH 208 Ð -
Ntilde 209 Ñ -
Ograve 210 Ò -
Oacute 211 Ó -
Ocirc 212 Ô -
Otilde 213 Õ -
Ouml 214 Ö -
times 215 × -
Oslash 216 Ø -
Ugrave 217 Ù -
Uacute 218 Ú -
Ucirc 219 Û -
Uuml 220 Ü -
Yacute 221 Ý -
THORN 222 Þ -
szlig 223 ß -
agrave 224 à -
aacute 225 á -
acirc 226 â -
atilde 227 ã -
auml 228 ä -
aring 229 å -
aelig 230 æ -
ccedil 231 ç -
egrave 232 è -
eacute 233 é -
ecirc 234 ê -
euml 235 ë -
igrave 236 ì -
iacute 237 í -
icirc 238 î -
iuml 239 ï -
eth 240 ð -
ntilde 241 ñ -
ograve 242 ò -
oacute 243 ó -
ocirc 244 ô -
otilde 245 õ -
ouml 246 ö -
divide 247 ÷ -
oslash 248 ø -
ugrave 249 ù -
uacute 250 ú -
ucirc 251 û -
uuml 252 ü -
yacute 253 ý -
thorn 254 þ -
yuml 255 ÿ - - - -
fnof 402 ƒ -
Alpha 913 Α -
Beta 914 Β -
Gamma 915 Γ -
Delta 916 Δ -
Epsilon 917 Ε -
Zeta 918 Ζ -
Eta 919 Η -
Theta 920 Θ -
Iota 921 Ι -
Kappa 922 Κ -
Lambda 923 Λ -
Mu 924 Μ -
Nu 925 Ν -
Xi 926 Ξ -
Omicron 927 Ο -
Pi 928 Π -
Rho 929 Ρ -
Sigma 931 Σ -
Tau 932 Τ -
Upsilon 933 Υ -
Phi 934 Φ -
Chi 935 Χ -
Psi 936 Ψ -
Omega 937 Ω -
alpha 945 α -
beta 946 β -
gamma 947 γ -
delta 948 δ -
epsilon 949 ε -
zeta 950 ζ -
eta 951 η -
theta 952 θ -
iota 953 ι -
kappa 954 κ -
lambda 955 λ -
mu 956 μ -
nu 957 ν -
xi 958 ξ -
omicron 959 ο -
pi 960 π -
rho 961 ρ -
sigmaf 962 ς -
sigma 963 σ -
tau 964 τ -
upsilon 965 υ -
phi 966 φ -
chi 967 χ -
psi 968 ψ -
omega 969 ω -
thetasym 977 ϑ -
upsih 978 ϒ -
piv 982 ϖ -
bull 8226 • -
hellip 8230 … -
prime 8242 ′ -
Prime 8243 ″ -
oline 8254 ‾ -
frasl 8260 ⁄ -
weierp 8472 ℘ -
image 8465 ℑ -
real 8476 ℜ -
trade 8482 ™ -
alefsym 8501 ℵ -
larr 8592 ← -
uarr 8593 ↑ -
rarr 8594 → -
darr 8595 ↓ -
harr 8596 ↔ -
crarr 8629 ↵ -
lArr 8656 ⇐ -
uArr 8657 ⇑ -
rArr 8658 ⇒ -
dArr 8659 ⇓ -
hArr 8660 ⇔ -
forall 8704 ∀ -
part 8706 ∂ -
exist 8707 ∃ -
empty 8709 ∅ -
nabla 8711 ∇ -
isin 8712 ∈ -
notin 8713 ∉ -
ni 8715 ∋ -
prod 8719 ∏ -
sum 8721 ∑ -
minus 8722 − -
lowast 8727 ∗ -
radic 8730 √ -
prop 8733 ∝ -
infin 8734 ∞ -
ang 8736 ∠ -
and 8743 ∧ -
or 8744 ∨ -
cap 8745 ∩ -
cup 8746 ∪ -
int 8747 ∫ -
there4 8756 ∴ -
sim 8764 ∼ -
cong 8773 ≅ -
asymp 8776 ≈ -
ne 8800 ≠ -
equiv 8801 ≡ -
le 8804 ≤ -
ge 8805 ≥ -
sub 8834 ⊂ -
sup 8835 ⊃ -
nsub 8836 ⊄ -
sube 8838 ⊆ -
supe 8839 ⊇ -
oplus 8853 ⊕ -
otimes 8855 ⊗ -
perp 8869 ⊥ -
sdot 8901 ⋅ -
lceil 8968 ⌈ -
rceil 8969 ⌉ -
lfloor 8970 ⌊ -
rfloor 8971 ⌋ -
lang 9001 ⟨ -
rang 9002 ⟩ -
loz 9674 ◊ -
spades 9824 ♠ -
clubs 9827 ♣ -
hearts 9829 ♥ -
diams 9830 ♦ - -
-
- -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Named Character Entities + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

Named Character Entities

+ + These are the character entity names supported by D. +

+ + Note: Not all will display properly in the Symbol + column in all browsers. +

+ + + +

+ +
Name Value Symbol + +
quot 34 " +
amp 38 & +
lt 60 < +
gt 62 > + +
OElig 338 Œ +
oelig 339 œ +
Scaron 352 Š +
scaron 353 š +
Yuml 376 Ÿ +
circ 710 ˆ +
tilde 732 ˜ +
ensp 8194   +
emsp 8195   +
thinsp 8201   +
zwnj 8204 ‌ +
zwj 8205 ‍ +
lrm 8206 ‎ +
rlm 8207 ‏ +
ndash 8211 – +
mdash 8212 — +
lsquo 8216 ‘ +
rsquo 8217 ’ +
sbquo 8218 ‚ +
ldquo 8220 “ +
rdquo 8221 ” +
bdquo 8222 „ +
dagger 8224 † +
Dagger 8225 ‡ +
permil 8240 ‰ +
lsaquo 8249 ‹ +
rsaquo 8250 › +
euro 8364 € + + + +
nbsp 160   +
iexcl 161 ¡ +
cent 162 ¢ +
pound 163 £ +
curren 164 ¤ +
yen 165 ¥ +
brvbar 166 ¦ +
sect 167 § +
uml 168 ¨ +
copy 169 © +
ordf 170 ª +
laquo 171 « +
not 172 ¬ +
shy 173 ­ +
reg 174 ® +
macr 175 ¯ +
deg 176 ° +
plusmn 177 ± +
sup2 178 ² +
sup3 179 ³ +
acute 180 ´ +
micro 181 µ +
para 182 ¶ +
middot 183 · +
cedil 184 ¸ +
sup1 185 ¹ +
ordm 186 º +
raquo 187 » +
frac14 188 ¼ +
frac12 189 ½ +
frac34 190 ¾ +
iquest 191 ¿ +
Agrave 192 À +
Aacute 193 Á +
Acirc 194 Â +
Atilde 195 Ã +
Auml 196 Ä +
Aring 197 Å +
AElig 198 Æ +
Ccedil 199 Ç +
Egrave 200 È +
Eacute 201 É +
Ecirc 202 Ê +
Euml 203 Ë +
Igrave 204 Ì +
Iacute 205 Í +
Icirc 206 Î +
Iuml 207 Ï +
ETH 208 Ð +
Ntilde 209 Ñ +
Ograve 210 Ò +
Oacute 211 Ó +
Ocirc 212 Ô +
Otilde 213 Õ +
Ouml 214 Ö +
times 215 × +
Oslash 216 Ø +
Ugrave 217 Ù +
Uacute 218 Ú +
Ucirc 219 Û +
Uuml 220 Ü +
Yacute 221 Ý +
THORN 222 Þ +
szlig 223 ß +
agrave 224 à +
aacute 225 á +
acirc 226 â +
atilde 227 ã +
auml 228 ä +
aring 229 å +
aelig 230 æ +
ccedil 231 ç +
egrave 232 è +
eacute 233 é +
ecirc 234 ê +
euml 235 ë +
igrave 236 ì +
iacute 237 í +
icirc 238 î +
iuml 239 ï +
eth 240 ð +
ntilde 241 ñ +
ograve 242 ò +
oacute 243 ó +
ocirc 244 ô +
otilde 245 õ +
ouml 246 ö +
divide 247 ÷ +
oslash 248 ø +
ugrave 249 ù +
uacute 250 ú +
ucirc 251 û +
uuml 252 ü +
yacute 253 ý +
thorn 254 þ +
yuml 255 ÿ + + + +
fnof 402 ƒ +
Alpha 913 Α +
Beta 914 Β +
Gamma 915 Γ +
Delta 916 Δ +
Epsilon 917 Ε +
Zeta 918 Ζ +
Eta 919 Η +
Theta 920 Θ +
Iota 921 Ι +
Kappa 922 Κ +
Lambda 923 Λ +
Mu 924 Μ +
Nu 925 Ν +
Xi 926 Ξ +
Omicron 927 Ο +
Pi 928 Π +
Rho 929 Ρ +
Sigma 931 Σ +
Tau 932 Τ +
Upsilon 933 Υ +
Phi 934 Φ +
Chi 935 Χ +
Psi 936 Ψ +
Omega 937 Ω +
alpha 945 α +
beta 946 β +
gamma 947 γ +
delta 948 δ +
epsilon 949 ε +
zeta 950 ζ +
eta 951 η +
theta 952 θ +
iota 953 ι +
kappa 954 κ +
lambda 955 λ +
mu 956 μ +
nu 957 ν +
xi 958 ξ +
omicron 959 ο +
pi 960 π +
rho 961 ρ +
sigmaf 962 ς +
sigma 963 σ +
tau 964 τ +
upsilon 965 υ +
phi 966 φ +
chi 967 χ +
psi 968 ψ +
omega 969 ω +
thetasym 977 ϑ +
upsih 978 ϒ +
piv 982 ϖ +
bull 8226 • +
hellip 8230 … +
prime 8242 ′ +
Prime 8243 ″ +
oline 8254 ‾ +
frasl 8260 ⁄ +
weierp 8472 ℘ +
image 8465 ℑ +
real 8476 ℜ +
trade 8482 ™ +
alefsym 8501 ℵ +
larr 8592 ← +
uarr 8593 ↑ +
rarr 8594 → +
darr 8595 ↓ +
harr 8596 ↔ +
crarr 8629 ↵ +
lArr 8656 ⇐ +
uArr 8657 ⇑ +
rArr 8658 ⇒ +
dArr 8659 ⇓ +
hArr 8660 ⇔ +
forall 8704 ∀ +
part 8706 ∂ +
exist 8707 ∃ +
empty 8709 ∅ +
nabla 8711 ∇ +
isin 8712 ∈ +
notin 8713 ∉ +
ni 8715 ∋ +
prod 8719 ∏ +
sum 8721 ∑ +
minus 8722 − +
lowast 8727 ∗ +
radic 8730 √ +
prop 8733 ∝ +
infin 8734 ∞ +
ang 8736 ∠ +
and 8743 ∧ +
or 8744 ∨ +
cap 8745 ∩ +
cup 8746 ∪ +
int 8747 ∫ +
there4 8756 ∴ +
sim 8764 ∼ +
cong 8773 ≅ +
asymp 8776 ≈ +
ne 8800 ≠ +
equiv 8801 ≡ +
le 8804 ≤ +
ge 8805 ≥ +
sub 8834 ⊂ +
sup 8835 ⊃ +
nsub 8836 ⊄ +
sube 8838 ⊆ +
supe 8839 ⊇ +
oplus 8853 ⊕ +
otimes 8855 ⊗ +
perp 8869 ⊥ +
sdot 8901 ⋅ +
lceil 8968 ⌈ +
rceil 8969 ⌉ +
lfloor 8970 ⌊ +
rfloor 8971 ⌋ +
lang 9001 ⟨ +
rang 9002 ⟩ +
loz 9674 ◊ +
spades 9824 ♠ +
clubs 9827 ♣ +
hearts 9829 ♥ +
diams 9830 ♦ + +
+
+ + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/enum.html dmd-0.136/dmd/html/d/enum.html --- dmd-0.135/dmd/html/d/enum.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/enum.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,241 +1,286 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Enums - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

Enums - Enumerated Types

- -
-	EnumDeclaration:
-		enum Identifier EnumBody
-		enum EnumBody
-		enum Identifier : EnumBaseType EnumBody
-		enum : EnumBaseType EnumBody
-
-	EnumBaseType:
-		Type
-
-	EnumBody:
-		;
-		{ EnumMembers }
-
-	EnumMembers:
-		EnumMember
-		EnumMember ,
-		EnumMember , EnumMembers
-
-	EnumMember:
-		Identifier
-		Identifier = Expression
-	
- - Enums are used to define a group of related integral constants. -

- - If the enum Identifier is present, the EnumMembers - are declared in the scope of the enum Identifier. - The enum Identifier declares a new type. -

- - If the enum Identifier is not present, then the enum - is an anonymous enum, and the EnumMembers are declared - in the scope the EnumDeclaration appears in. - No new type is created; the EnumMembers have the type of the - EnumBaseType. -

- - The EnumBaseType is the underlying type of the enum. - It must be an integral type. - If omitted, it defaults to int. - -

-	enum { A, B, C }	// anonymous enum
-	
- - Defines the constants A=0, B=1, C=2 in a manner equivalent to: - -
-	const int A = 0;
-	const int B = 1;
-	const int C = 2;
-	
- - Whereas: - -
-	enum X { A, B, C }	// named enum
-	
- - Define a new type X which has values X.A=0, X.B=1, X.C=2 -

- - Named enum members can be implicitly cast to integral types, but integral types - cannot be implicitly cast to an enum type. -

- - Enums must have at least one member. -

- - If an Expression is supplied for an enum member, the value - of the member is set to the result of the Expression. - The Expression must be resolvable at compile time. - Subsequent enum members with no Expression are set to the - value of the previous member plus one: - -

-	enum { A, B = 5+7, C, D = 8, E }
-	
- - Sets A=0, B=12, C=13, D=8, and E=9. - -

Enum Properties

- -
-	.min			Smallest value of enum
-	.max			Largest value of enum
-	.sizeof			Size of storage for an enumerated value
-
-	For example:
-
-	X.min			is X.A
-	X.max			is X.C
-	X.sizeof		is same as int.sizeof
-
- -

Initialization of Enums

- - In the absence of an explicit initializer, an enum variable - is initialized to the first enum value. - -
-	enum X { A=3, B, C }
-	X x;		// x is initialized to 3
-	
- -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Enums + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

Enums - Enumerated Types

+ +
EnumDeclaration:
+	enum Identifier EnumBody
+	enum EnumBody
+	enum Identifier : EnumBaseType EnumBody
+	enum : EnumBaseType EnumBody
+
+EnumBaseType:
+	Type
+
+EnumBody:
+	;
+	{ EnumMembers }
+
+EnumMembers:
+	EnumMember
+	EnumMember ,
+	EnumMember , EnumMembers
+
+EnumMember:
+	Identifier
+	Identifier = Expression
+
+ + Enums are used to define a group of related integral constants. +

+ + If the enum Identifier is present, the EnumMembers + are declared in the scope of the enum Identifier. + The enum Identifier declares a new type. +

+ + If the enum Identifier is not present, then the enum + is an anonymous enum, and the EnumMembers are declared + in the scope the EnumDeclaration appears in. + No new type is created; the EnumMembers have the type of the + EnumBaseType. +

+ + The EnumBaseType is the underlying type of the enum. + It must be an integral type. + If omitted, it defaults to int. + +

enum { A, B, C }	// anonymous enum
+
+ + Defines the constants A=0, B=1, C=2 in a manner equivalent to: + +
const int A = 0;
+const int B = 1;
+const int C = 2;
+
+ + Whereas: + +
enum X { A, B, C }	// named enum
+
+ + Define a new type X which has values X.A=0, X.B=1, X.C=2 +

+ + Named enum members can be implicitly cast to integral types, but integral types + cannot be implicitly cast to an enum type. +

+ + Enums must have at least one member. +

+ + If an Expression is supplied for an enum member, the value + of the member is set to the result of the Expression. + The Expression must be resolvable at compile time. + Subsequent enum members with no Expression are set to the + value of the previous member plus one: + +

enum { A, B = 5+7, C, D = 8, E }
+
+ + Sets A=0, B=12, C=13, D=8, and E=9. + +

Enum Properties

+ +
+.min			Smallest value of enum
+.max			Largest value of enum
+.sizeof			Size of storage for an enumerated value
+
+For example:
+
+X.min			is X.A
+X.max			is X.C
+X.sizeof		is same as int.sizeof
+
+ +

Initialization of Enums

+ + In the absence of an explicit initializer, an enum variable + is initialized to the first enum value. + +
enum X { A=3, B, C }
+X x;		// x is initialized to 3
+
+ + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/errors.html dmd-0.136/dmd/html/d/errors.html --- dmd-0.135/dmd/html/d/errors.html 2005-09-18 11:39:24.000000000 +0200 +++ dmd-0.136/dmd/html/d/errors.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,333 +1,384 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Errors - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions
Statements
Arrays
Structs & Unions
Classes
Interfaces
Enums
Functions
Operator Overloading
Templates
Mixins
Contracts
Conditional Compilation
Handling errors
Garbage Collection
Memory Management
Floating Point
Inline Assembler
Documentation Comments
Interfacing To C
Portability Guide
Embedding D in HTML
Named Character Entities
Application Binary Interface
-
-
- - - -

Error Handling in D

- -All programs have to deal with errors. Errors are unexpected conditions that -are not part of the normal operation of a program. Examples of common errors -are: - -
    -
  • Out of memory. -
  • Out of disk space. -
  • Invalid file name. -
  • Attempting to write to a read-only file. -
  • Attempting to read a non-existent file. -
  • Requesting a system service that is not supported. -
- -

The Error Handling Problem

- -The traditional C way of detecting and reporting errors is not traditional, -it is ad-hoc and varies from function to function, including: - -
    -
  • Returning a NULL pointer. -
  • Returning a 0 value. -
  • Returning a non-zero error code. -
  • Requiring errno to be checked. -
  • Requiring that a function be called to check if the previous - function failed. -
- -To deal with these possible errors, tedious error handling code must be added -to each function call. If an error happened, code must be written to recover -from the error, and the error must be reported to the user in some user friendly -fashion. If an error cannot be handled locally, it must be explicitly -propagated back to its caller. -The long list of errno values needs to be converted into appropriate -text to be displayed. Adding all the code to do this can consume a large part -of the time spent coding a project - and still, if a new errno value is added -to the runtime system, the old code can not properly display a meaningful -error message. -

- -Good error handling code tends to clutter up what otherwise would be a neat -and clean looking implementation. -

- -Even worse, good error handling code is itself error prone, tends to be the -least tested (and therefore buggy) part of the project, and is frequently -simply omitted. The end result is likely a "blue screen of death" as the -program failed to deal with some unanticipated error. -

- -Quick and dirty programs are not worth writing tedious error handling code -for, and so such utilities tend to be like using a table saw with no -blade guards. -

- -What's needed is an error handling philosophy and methodology that is: - -

    -
  • Standardized - consistent usage makes it more useful. -
  • Produces a reasonable result even if the programmer fails - to check for errors. -
  • Allows old code to be reused with new code without having - to modify the old code to be compatible with new error types. -
  • No errors get inadvertently ignored. -
  • Allows 'quick and dirty' utilities to be written that still - correctly handle errors. -
  • Easy to make the error handling source code look good. -
- -

The D Error Handling Solution

- -Let's first make some observations and assumptions about errors: - -
    -
  • Errors are not part of the normal flow of a program. Errors - are exceptional, unusual, and unexpected. -
  • Because errors are unusual, execution of error handling code - is not performance critical. -
  • The normal flow of program logic is performance critical. -
  • All errors must be dealt with in some way, either by - code explicitly written to handle them, or by some system default - handling. -
  • The code that detects an error knows more about the error - than the code that must recover from the error. -
- -The solution is to use exception handling to report errors. All errors are -objects derived from abstract class Error. class Error has a pure virtual -function called toString() which produces a char[] with a human readable -description of the error. -

- -If code detects an error like "out of memory," then an Error is thrown -with a message saying "Out of memory". The function call stack is unwound, -looking for a handler for the Error. Finally blocks are executed as the -stack is unwound. If an error handler is found, execution resumes there. If -not, the default Error handler is run, which displays the message and -terminates the program. -

- -How does this meet our criteria? - -

-
Standardized - consistent usage makes it more useful. -
This is the D way, and is used consistently in the D - runtime library and examples. - -
Produces a reasonable result even if the programmer fails - to check for errors. -
If no catch handlers are there for the errors, then the - program gracefully exits through the default error handler - with an appropriate message. - -
Allows old code to be reused with new code without having - to modify the old code to be compatible with new error types. -
Old code can decide to catch all errors, or only specific ones, - propagating the rest upwards. In any case, there is no more - need to correlate error numbers with messages, the correct message - is always supplied. - -
No errors get inadvertently ignored. -
Error exceptions get handled one way or another. There is nothing - like a NULL pointer return indicating an error, followed by trying to - use that NULL pointer. - -
Allows 'quick and dirty' utilities to be written that still - correctly handle errors. -
Quick and dirty code need not write any error handling code at - all, and don't need to check for errors. The errors will be caught, - an appropriate message displayed, and the program gracefully shut down - all by default. - -
Easy to make the error handling source code look good. -
The try/catch/finally statements look a lot nicer than endless - if (error) goto errorhandler; statements. -
- -How does this meet our assumptions about errors? - -
-
Errors are not part of the normal flow of a program. Errors - are exceptional, unusual, and unexpected. -
D exception handling fits right in with that. - -
Because errors are unusual, execution of error handling code - is not performance critical. -
Exception handling stack unwinding is a relatively slow process. - -
The normal flow of program logic is performance critical. -
Since the normal flow code does not have to check every - function call for error returns, it can be realistically faster - to use exception handling for the errors. - -
All errors must be dealt with in some way, either by - code explicitly written to handle them, or by some system default - handling. -
If there's no handler for a particular error, it is handled - by the runtime library default handler. If an error is ignored, - it is because the programmer specifically added code to ignore - an error, which presumably means it was intentional. - -
The code that detects an error knows more about the error - than the code that must recover from the error. -
There is no more need to translate error codes into human - readable strings, the correct string is generated by the error - detection code, not the error recovery code. This also leads to - consistent error messages for the same error between applications. -
- - - -
-

Feedback and Comments

- -

Add feedback and comments regarding this - page.

- - - - - - - - - - - + + + + + + + + +D Programming Language - Errors + + + + +
+ www.digitalmars.com + + Home + | Search + | D + | Comments + +
Last update Tue Oct 4 18:05:29 2005 +
+
+ + + + + + + + +
+ +
+
+ + + + + +
+
+ +
+D
+Language
+Phobos
+Comparisons +
+
+ +· Lexical
+ + +· Modules
+ + +· Declarations
+ + +· Types
+ + +· Properties
+ + +· Attributes
+ + +· Pragmas
+ + +· Expressions
+ + +· Statements
+ + +· Arrays
+ + +· Structs & Unions
+ + +· Classes
+ + +· Interfaces
+ + +· Enums
+ + +· Functions
+ + +· Operator Overloading
+ + +· Templates
+ + +· Mixins
+ + +· Contracts
+ + +· Conditional Compilation
+ + +· Handling errors
+ + +· Garbage Collection
+ + +· Memory Management
+ + +· Floating Point
+ + +· Inline Assembler
+ + +· Documentation Comments
+ + +· Interfacing To C
+ + +· Portability Guide
+ + +· Embedding D in HTML
+ + +· Named Character Entities
+ + +· Application Binary Interface
+ + +
+
+ + +

Error Handling in D

+ +All programs have to deal with errors. Errors are unexpected conditions that +are not part of the normal operation of a program. Examples of common errors +are: + +
    +
  • Out of memory. +
  • Out of disk space. +
  • Invalid file name. +
  • Attempting to write to a read-only file. +
  • Attempting to read a non-existent file. +
  • Requesting a system service that is not supported. +
+ +

The Error Handling Problem

+ +The traditional C way of detecting and reporting errors is not traditional, +it is ad-hoc and varies from function to function, including: + +
    +
  • Returning a NULL pointer. +
  • Returning a 0 value. +
  • Returning a non-zero error code. +
  • Requiring errno to be checked. +
  • Requiring that a function be called to check if the previous + function failed. +
+ +To deal with these possible errors, tedious error handling code must be added +to each function call. If an error happened, code must be written to recover +from the error, and the error must be reported to the user in some user friendly +fashion. If an error cannot be handled locally, it must be explicitly +propagated back to its caller. +The long list of errno values needs to be converted into appropriate +text to be displayed. Adding all the code to do this can consume a large part +of the time spent coding a project - and still, if a new errno value is added +to the runtime system, the old code can not properly display a meaningful +error message. +

+ +Good error handling code tends to clutter up what otherwise would be a neat +and clean looking implementation. +

+ +Even worse, good error handling code is itself error prone, tends to be the +least tested (and therefore buggy) part of the project, and is frequently +simply omitted. The end result is likely a "blue screen of death" as the +program failed to deal with some unanticipated error. +

+ +Quick and dirty programs are not worth writing tedious error handling code +for, and so such utilities tend to be like using a table saw with no +blade guards. +

+ +What's needed is an error handling philosophy and methodology that is: + +

    +
  • Standardized - consistent usage makes it more useful. +
  • Produces a reasonable result even if the programmer fails + to check for errors. +
  • Allows old code to be reused with new code without having + to modify the old code to be compatible with new error types. +
  • No errors get inadvertently ignored. +
  • Allows 'quick and dirty' utilities to be written that still + correctly handle errors. +
  • Easy to make the error handling source code look good. +
+ +

The D Error Handling Solution

+ +Let's first make some observations and assumptions about errors: + +
    +
  • Errors are not part of the normal flow of a program. Errors + are exceptional, unusual, and unexpected. +
  • Because errors are unusual, execution of error handling code + is not performance critical. +
  • The normal flow of program logic is performance critical. +
  • All errors must be dealt with in some way, either by + code explicitly written to handle them, or by some system default + handling. +
  • The code that detects an error knows more about the error + than the code that must recover from the error. +
+ +The solution is to use exception handling to report errors. All errors are +objects derived from abstract class Error. class Error has a pure virtual +function called toString() which produces a char[] with a human readable +description of the error. +

+ +If code detects an error like "out of memory," then an Error is thrown +with a message saying "Out of memory". The function call stack is unwound, +looking for a handler for the Error. Finally blocks are executed as the +stack is unwound. If an error handler is found, execution resumes there. If +not, the default Error handler is run, which displays the message and +terminates the program. +

+ +How does this meet our criteria? + +

+
Standardized - consistent usage makes it more useful. +
This is the D way, and is used consistently in the D + runtime library and examples. + +
Produces a reasonable result even if the programmer fails + to check for errors. +
If no catch handlers are there for the errors, then the + program gracefully exits through the default error handler + with an appropriate message. + +
Allows old code to be reused with new code without having + to modify the old code to be compatible with new error types. +
Old code can decide to catch all errors, or only specific ones, + propagating the rest upwards. In any case, there is no more + need to correlate error numbers with messages, the correct message + is always supplied. + +
No errors get inadvertently ignored. +
Error exceptions get handled one way or another. There is nothing + like a NULL pointer return indicating an error, followed by trying to + use that NULL pointer. + +
Allows 'quick and dirty' utilities to be written that still + correctly handle errors. +
Quick and dirty code need not write any error handling code at + all, and don't need to check for errors. The errors will be caught, + an appropriate message displayed, and the program gracefully shut down + all by default. + +
Easy to make the error handling source code look good. +
The try/catch/finally statements look a lot nicer than endless + if (error) goto errorhandler; statements. +
+ +How does this meet our assumptions about errors? + +
+
Errors are not part of the normal flow of a program. Errors + are exceptional, unusual, and unexpected. +
D exception handling fits right in with that. + +
Because errors are unusual, execution of error handling code + is not performance critical. +
Exception handling stack unwinding is a relatively slow process. + +
The normal flow of program logic is performance critical. +
Since the normal flow code does not have to check every + function call for error returns, it can be realistically faster + to use exception handling for the errors. + +
All errors must be dealt with in some way, either by + code explicitly written to handle them, or by some system default + handling. +
If there's no handler for a particular error, it is handled + by the runtime library default handler. If an error is ignored, + it is because the programmer specifically added code to ignore + an error, which presumably means it was intentional. + +
The code that detects an error knows more about the error + than the code that must recover from the error. +
There is no more need to translate error codes into human + readable strings, the correct string is generated by the error + detection code, not the error recovery code. This also leads to + consistent error messages for the same error between applications. +
+ + + + +
+ + + + + + + + + + + + + + + diff -uNr dmd-0.135/dmd/html/d/expression.html dmd-0.136/dmd/html/d/expression.html --- dmd-0.135/dmd/html/d/expression.html 2005-09-18 11:39:22.000000000 +0200 +++ dmd-0.136/dmd/html/d/expression.html 2005-10-04 18:05:30.000000000 +0200 @@ -1,1449 +1,1452 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D Programming Language - Expressions - - - - -www.digitalmars.com - -Home -| Search -| D -| Comments - -
-Last update Sun Sep 18 2005 -
- - -
-
-
- - - - - -
-D
-Language
-Phobos
-Comparisons -
-
-Lexical
Modules
Declarations
Types
Properties
Attributes
Pragmas
Expressions