- `);
- foreach (child; nav.children)
- dumpNav(child, level+1);
- f.writeln(t, `
- `);
- dumpNav(nav);
- f.writeln(`
- `);
- foreach (keyNorm;keywordList)
- {
- auto urlList = keywords[keyNorm];
- f.writeln(
-`
- `); - } - f.writeln( -`
Access Control
- - $(P Access to class members is controlled using $(GLINK2 attribute, ProtectionAttribute)s. - The default protection attribute is $(D public). - Access control does not affect visibility. - ) - -Fields
- - $(P Class members are always accessed with the . operator. - ) - - $(P Members of a base class can be accessed by prepending the name of - the base class followed by a dot:) - ---- -class A { int a; } -class B : A { int a; } - -void foo(B b) { - b.a = 3; // accesses field B.a - b.A.a = 4; // accesses field A.a ---- - - $(P 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
- - $(P The $(B .offsetof) property gives the offset in bytes of the field - from the beginning of the class instantiation. - $(B .offsetof) can only be applied to - expressions which produce the type of - the field itself, not the class type: - ) - ------- -class Foo { - int x; -} -... -void test(Foo foo) { - size_t o; - - o = Foo.x$(B .offsetof); // error, Foo.x needs a 'this' reference - o = foo.x$(B .offsetof); // ok -} ------- - -Class Properties
- - $(P The $(B .tupleof) property returns an $(I ExpressionTuple) - of all the fields - in the class, excluding the hidden fields and the fields in the - base class. - ) ---- -class Foo { int x; long y; } -void test(Foo foo) { - foo.tupleof[0] = 1; // set foo.x to 1 - foo.tupleof[1] = 2; // set foo.y to 2 - foreach (x; foo.tupleof) - writef(x); // prints 12 -} ---- - - $(P The properties $(B .__vptr) and $(B .__monitor) give access - to the class object's vtbl[] and monitor, respectively, but - should not be used in user code. - ) - -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. - -$(LNAME2 member-functions, Member Functions)
- - $(P Non-static member functions have an extra hidden parameter - called $(I this) through which the class object's other members - can be accessed. - ) - -$(V2 - $(P Non-static member functions can have, in addition to the usual - $(GLINK2 declaration, FunctionAttribute)s, the attributes - $(D const), $(D immutable), $(D shared), or $(D inout). - These attributes apply to the hidden $(I this) parameter. - ) ---- -class C { - int a; - const void foo() { - a = 3; // error, 'this' is const - } - void foo() immutable { - a = 3; // error, 'this' is immutable - } ---- -) - -$(LNAME2 synchronized-functions, Synchronized Functions)
- - $(P Synchronized class member functions have the storage class - $(CODE synchronized). - A static member function is synchronized on the $(I classinfo) - object for the class, which means that one monitor is used - for all static synchronized member functions for that class. - For non-static synchronized functions, the monitor used is - part of the class object. For example: - ) - ---- -class Foo { - synchronized void bar() { ...statements... } -} ---- - - $(P is equivalent to (as far as the monitors go): - ) - ---- -class Foo { - void bar() { - synchronized (this) { ...statements... } - } -} ---- - - $(P Structs do not have synchronized member functions.) - -$(LNAME2 constructors, Constructors)
- -$(GRAMMAR -$(GNAME Constructor): - $(B this) $(GLINK2 declaration, Parameters) $(GLINK2 function, FunctionBody) -$(V2 $(GLINK2 template, TemplatedConstructor)) -) - - $(P Members are always initialized to the - $(LNAME2 class-default-initializer, 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 $(B this) - and having no return value: - ------- -class Foo { - $(B this)(int x) // declare constructor for Foo - { ... - } - $(B this)() - { ... - } -} ------- - - Base class construction is done by calling the base class - constructor by the name $(B super): - ------- -class A { this(int y) { } } - -class B : A { - int j; - this() { - ... - $(B super)(3); // call base constructor A.this(3) - ... - } -} ------- - - $(P Constructors can also call other constructors for the same class - in order to share common initializations - $(LNAME2 delegating-constructors, (this is called delegating constructors)): - ) - ------- -class C { - int j; - this() { - ... - } - this(int i) { - $(B this)(); - j = i; - } -} ------- - - If no call to constructors via $(B this) or $(B super) appear - in a constructor, and the base class has a constructor, a call - to $(B 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() { } ------- - - $(P is implicitly generated.) - - $(P Class object construction is very flexible, but some restrictions - apply:) - - $(OL - $(LI It is illegal for constructors to mutually call each other, - although the compiler is not required to detect it. It will result - in undefined behavior. - ------- -this() { this(1); } -this(int i) { this(); } // illegal, cyclic constructor calls ------- - ) - - $(LI If any constructor call appears inside a constructor, any - path through the constructor must make exactly one constructor - call: - ------- -this() { a || super(); } // illegal - -this() { (a) ? this(1) : super(); } // ok - -this() { - for (...) { - super(); // illegal, inside loop - } -} ------- - ) - - $(LI It is illegal to refer to $(B this) implicitly or explicitly - prior to making a constructor call.) - - $(LI Constructor calls cannot appear after labels (in order to make - it easy to check for the previous conditions in the presence of goto's).) - - ) - - $(P Instances of class objects are created with $(I NewExpression)s:) - ------- -A a = new A(3); ------- - - $(P The following steps happen:) - -$(OL - $(LI Storage is allocated for the object. - If this fails, rather than return $(B null), an - $(B OutOfMemoryError) is thrown. - Thus, tedious checks for null references are unnecessary. - ) - - $(LI The raw data is statically initialized using the values provided - in the class definition. - The pointer to the vtbl[] (the array of pointers to virtual functions) - is assigned. - This ensures that constructors are - passed fully formed objects for which virtual functions can be called. - This operation is equivalent to doing a memory copy 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. - ) - - $(LI If there is a constructor defined for the class, - the constructor matching the - argument list is called. - ) - - $(LI If class invariant checking is turned on, the class invariant - is called at the end of the constructor. - ) -) - -
$(LNAME2 destructors, Destructors)
- -$(GRAMMAR -$(GNAME Destructor): - $(B ~ this ( )) $(GLINK2 function, FunctionBody) -) - - The garbage collector calls the destructor function when the object - is deleted. The syntax - is: - ------- -class Foo { - ~this() // destructor for Foo - { - } -} ------- - - $(P There can be only one destructor per class, the destructor - does not have any parameters, - and has no attributes. It is always virtual. - ) - - $(P The destructor is expected to release any resources held by the - object. - ) - - $(P 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. - ) - - $(P The destructor for the super class automatically gets called when - the destructor ends. There is no way to call the super destructor - explicitly. - ) - - $(P 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. - This means that - 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 may no longer be valid. This means that destructors - cannot reference sub objects. - This rule does not apply to auto objects or objects deleted - with the $(I DeleteExpression), as the destructor is not being run - by the garbage collector, meaning all references are valid. - ) - - $(P Objects referenced from the data segment never get collected - by the gc. - ) - -Static Constructors
- -$(GRAMMAR -$(GNAME StaticConstructor): - $(B static this ( )) $(GLINK2 function, FunctionBody) -) - - $(P - $(V1 A static constructor is a function that performs - initializations before the $(D main()) function gets control.) - - $(V2 A static constructor is a function that performs - initializations of thread local data before the $(D main()) function gets control for - the main thread, and upon thread startup.) - - Static constructors are used to initialize - static class members - with values that cannot be computed at compile time. - ) - - $(P 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 $(D 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 - - $(B static this)() // static constructor - { - a = b + 1; // a is set to 2 - b = a * 2; // b is set to 4 - } -} ------- - - $(P - $(V1 - If $(D main()) returns normally - (does not throw an exception), the static destructor is added - to the list of functions to be - called on program termination. - ) - $(V2 - If $(D main()) or the thread returns normally, - (does not throw an exception), the static destructor is added - to the list of functions to be - called on thread termination. - ) - Static constructors have empty parameter lists. - ) - - $(P - 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. - ) - - $(P - The $(B static) in the static constructor declaration is not - an attribute, it must appear immediately before the $(B 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 Destructors
- -$(GRAMMAR -$(GNAME StaticDestructor): - $(B static ~ this ( )) $(GLINK2 function, FunctionBody) -) - - A static destructor is defined as a special static function with the - syntax $(D static ~this()). - ------- -class Foo { - static ~this() // static destructor - { - } -} ------- - - $(P - A static destructor gets called on $(V1 program)$(V2 thread) 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. - ) - - $(P - The $(B static) in the static destructor declaration is not - an attribute, it must appear immediately before the $(B ~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 -} ------- - -$(V2 -Shared Static Constructors
- -$(GRAMMAR -$(GNAME SharedStaticConstructor): - $(B shared static this ( )) $(GLINK2 function, FunctionBody) -) - - $(P Shared static constructors are executed before any $(GLINK StaticConstructor)s, - and are intended for initializing any shared global data. - ) - -Shared Static Destructors
- -$(GRAMMAR -$(GNAME SharedStaticDestructor): - $(B shared static ~ this ( )) $(GLINK2 function, FunctionBody) -) - - $(P Shared static destructors are executed at program termination - in the reverse order that - $(GLINK SharedStaticConstructor)s were executed. - ) -) - -$(LNAME2 invariants, Class Invariants)
- -$(GRAMMAR -$(GNAME Invariant): - $(B invariant ( )) $(GLINK2 statement, 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; - - $(B invariant()) { - assert(1 <= day && day <= 31); - assert(0 <= hour && hour < 24); - } -} ------- - - $(P 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. For public or exported functions, - the order of execution is: - ) - - $(OL - $(LI preconditions) - $(LI invariant) - $(LI body) - $(LI invariant) - $(LI postconditions) - ) - - $(P 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. - ) - - $(V2 $(P Invariants are implicitly const.)) - - $(P Since the invariant is called at the start of public or - exported members, such members should not be called from - constructors. - ) - ------- -class Foo { - public void f() { } - private void g() { } - - $(B 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
-------
-
- Invariants contain assert expressions, and so when they fail,
- they throw a $(D AssertError)s.
- Class invariants are inherited, that is,
- any class invariant is implicitly anded with the invariants of its base
- classes.
- - - There can be only one $(I Invariant) per class. -
- - When compiling for release, the invariant code is not generated, and the compiled program - runs at maximum speed. - -
$(LNAME2 allocators, Class Allocators)
- -$(GRAMMAR -$(GNAME ClassAllocator): - $(B new) $(GLINK2 declaration, Parameters) $(GLINK2 function, FunctionBody) -) - - 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 - $(D void*). - If the allocator fails, it must not return a $(B 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 $(B new) in the $(I NewExpression): - ------- -class Foo { - this(char[] a) { ... } - - new(uint size, int x, int y) { - ... - } -} - -... - -new(1,2) Foo(a); // calls new(Foo.sizeof,1,2) ------- - - $(P Derived classes inherit any allocator from their base class, - if one is not specified. - ) - - $(P The class allocator is not called if the instance is created - on the stack. - ) - - $(P See also - $(DPLLINK memory.html#newdelete, Explicit Class Instance Allocation). - ) - -$(LNAME2 deallocators, Class Deallocators)
- -$(GRAMMAR -$(GNAME ClassDeallocator): - $(B delete) $(GLINK2 declaration, Parameters) $(GLINK2 function, FunctionBody) -) - - A class member function of the form: - ------- -delete(void *p) { - ... -} ------- - - is called a class deallocator. - The deallocator must have exactly one parameter of type $(D void*). - Only one can be specified for a class. - When a delete expression: - ------- -delete f; ------- - - $(P 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. - ) - - $(P Derived classes inherit any deallocator from their base class, - if one is not specified. - ) - - $(P The class allocator is not called if the instance is created - on the stack. - ) - - $(P See also - $(DPLLINK memory.html#newdelete, Explicit Class Instance Allocation). - ) - -$(V2 -$(LNAME2 AliasThis, Alias This)
- -$(GRAMMAR -$(GNAME AliasThis): - $(B alias) $(I Identifier) $(B this;) -) - - $(P An $(I AliasThis) declaration names a member to subtype. - The $(I Identifier) names that member. - ) - - $(P A class or struct can be implicitly converted to the $(I AliasThis) - member. - ) - ---- -struct S { - int x; - alias x this; -} - -int foo(int i) { return i * 2; } - -void test() { - S s; - s.x = 7; - int i = -s; // i == -7 - i = s + 8; // i == 15 - i = s + s; // i == 14 - i = 9 + s; // i == 16 - i = foo(s); // implicit conversion to int -} ---- - - $(P If the member is a class or struct, undefined lookups will - be forwarded to the $(I AliasThis) member. - ) - ---- -struct Foo -{ - int baz = 4; - int get() { return 7; } -} - -class Bar -{ - Foo foo; - alias foo this; -} - -void test() { - auto bar = new Bar; - int i = bar.baz; // i == 4 - i = bar.get(); // i == 7 -} ---- - - $(P If the $(I Identifier) refers to a property member - function with no parameters, conversions and undefined - lookups are forwarded to the return value of the function. - ) - ---- -struct S -{ - int x; - @property int get() { - return x * 2; - } - alias get this; -} - -void test() { - S s; - s.x = 2; - int i = s; // i == 4 -} ---- - - $(P Multiple $(I AliasThis) are allowed. For implicit conversions - and forwarded lookups, all $(I AliasThis) declarations are attempted; - if more than one $(I AliasThis) is eligible, the ambiguity is - disallowed by raising an error. - ) -) - -$(LNAME2 auto, Scope Classes)
- - A scope class is a class with the $(B scope) attribute, as in: - ------- -scope class Foo { ... } ------- - - The scope characteristic is inherited, so if any classes derived - from a scope class are also scope. -- - An scope class reference can only appear as a function local variable. - It must be declared as being $(B scope): - ------- -scope class Foo { ... } - -void func() { - Foo f; // error, reference to scope class must be scope - scope Foo g = new Foo(); // correct -} ------- - - When an scope 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. - -
$(LNAME2 final, Final Classes)
- - $(P Final classes cannot be subclassed:) - ---- -final class A { } -class B : A { } // error, class A is final ---- - -$(LNAME2 nested, Nested Classes)
- - A $(I 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 $(B static) attribute, then it can - not access variables of the enclosing scope that are local to the - stack or need a $(B this): - ------- -class Outer { - int m; - static int n; - - static class Inner { - int foo() { - return m; // Error, Inner is static and m needs a $(B 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 $(B 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 -} ------- - -$(V1 - 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 -} ------- -) - - $(P A $(I this) can be supplied to the creation of an - inner class instance by prefixing it to the $(I NewExpression): - ) - ---------- -class Outer { - int a; - - class Inner { - int foo() { - return a; - } - } -} - -int bar() { - Outer o = new Outer; - o.a = 3; - Outer.Inner oi = $(B o).new Inner; - return oi.foo(); // returns 3 -} ---------- - - $(P Here $(B o) supplies the $(I this) to the outer class - instance of $(B Outer). - ) - - $(P The property $(B .outer) used in a nested class gives the - $(B this) pointer to its enclosing class. If the enclosing - context is not a class, the $(B .outer) will give the pointer - to it as a $(B void*) type. - ) - ----- -class Outer { - class Inner { - Outer foo() { - return this.$(B outer); - } - } - - void bar() { - Inner i = new Inner; - assert(this == i.foo()); - } -} - -void test() { - Outer o = new Outer; - o.bar(); -} ----- - -
$(LNAME2 anonymous, Anonymous Nested Classes)
- - $(P An anonymous nested class is both defined and instantiated with - a $(I NewAnonClassExpression): - ) - -$(GRAMMAR -$(GNAME NewAnonClassExpression): - $(B new) $(GLINK2 expression, AllocatorArguments)$(OPT) $(B class) $(I ClassArguments)$(OPT) $(GLINK SuperClass)$(OPT) $(GLINK Interfaces)$(OPT) $(GLINK ClassBody) - -$(GNAME ClassArguments): - $(B $(LPAREN)) $(GLINK2 expression, ArgumentList)$(OPT) $(B $(RPAREN)) -) - - $(P which is equivalent to: - ) - ------- -class $(I Identifier) : $(I SuperClass) $(I Interfaces) - $(I ClassBody) - -new ($(I ArgumentList)) $(I Identifier) ($(I ArgumentList)); ------- - - $(P where $(I Identifier) is the name generated for the anonymous - nested class. - ) - -$(V2 -$(SECTION3 Const Immutable and Shared Classes, - $(P If a $(I ClassDeclaration) has a $(CODE const), $(CODE immutable) - or $(CODE shared) storage class, then it is as if each member of the class - was declared with that storage class. - If a base class is const, immutable or shared, then all classes derived - from it are also const, immutable or shared. - ) -) -) - -) -) - -Macros: - TITLE=Classes - WIKI=Class - CATEGORY_SPEC=$0 - FOO= - diff --git a/community.dd b/community.dd new file mode 100644 index 0000000000..f20306229c --- /dev/null +++ b/community.dd @@ -0,0 +1,6 @@ +Ddoc + +$(D_S Community, $(NAVIGATION_COMMUNITY)) + +Macros: + TITLE=Community diff --git a/comparison.dd b/comparison.dd index fbf0742eb3..9737a7ccee 100644 --- a/comparison.dd +++ b/comparison.dd @@ -1,595 +1,149 @@ Ddoc -$(COMMUNITY $(B D) vs Other Languages, - - $(BLOCKQUOTE William Nerdspeare, - To D, or not to D. - ) - - $(P This table is a quick and rough list of various features of - $(B D) - that can be used to compare with other languages. - While many capabilities are available with standard libraries, this - table is for features built in to the core language itself. - $(LINK2 builtin.html, Rationale). - ) - -| Feature | -$(B D) | - ) - - - - - $(TR - $(TD Garbage Collection) - $(YES1 garbage.html) - ) - - $(TR -Functions | - ) - - $(TR - $(TD Function delegates) - $(YES1 type.html#delegates) - ) - - $(TR - $(TD Function overloading) - $(YES1 function.html#function-overloading) - ) - - $(TR - $(TD Out function parameters) - $(YES1 function.html#parameters) - ) - - $(TR - $(TD Nested functions) - $(YES1 function.html#nested) - ) - - $(TR - $(TD Function literals) - $(YES1 expression.html#FunctionLiteral) - ) - - $(TR - $(V1 $(TD Dynamic closures)) - $(V2 $(TD Closures)) - $(YES1 function.html#closures) - ) - - $(TR - $(TD Typesafe variadic arguments) - $(YES1 function.html#variadic) - ) - - $(TR - $(TD Lazy function argument evaluation) - $(YES1 lazy-evaluation.html) - ) - - $(TR - $(TD Compile time function evaluation) - $(YES1 function.html#interpretation) - ) - - $(TR -Arrays | - ) - - $(TR - $(TD Lightweight arrays) - $(YES1 arrays.html) - ) - - $(TR - $(TD Resizeable arrays) - $(YES1 arrays.html#resize) - ) - - $(TR - $(TD Built-in strings) - $(YES1 arrays.html#strings) - ) - - $(TR - $(TD Array slicing) - $(YES1 arrays.html#slicing) - ) - - $(TR - $(TD Array bounds checking) - $(YES1 arrays.html#bounds) - ) - - $(TR - $(TD Array literals) - $(YES1 expression.html#ArrayLiteral) - ) - - $(TR - $(TD Associative arrays) - $(YES1 arrays.html#associative) - ) - - $(TR - $(TD Strong typedefs) - $(YES1 declaration.html#typedef) - ) - - $(TR - $(TD String switches) - $(YES1 statement.html#SwitchStatement) - ) - - $(TR - $(TD Aliases) - $(YES1 declaration.html#alias) - ) - - $(TR -OOP | - ) - - $(TR - $(TD Object Oriented) - $(YES) - ) - - $(TR - $(TD Multiple Inheritance) - $(NO) - ) - - $(TR - $(TD Interfaces) - $(YES1 interface.html) - ) - - $(TR - $(TD Operator overloading) - $(YES1 operatoroverloading.html) - ) - - $(TR - $(TD Modules) - $(YES1 module.html) - ) - - $(TR - $(TD Dynamic class loading) - $(NO) - ) - - $(TR - $(TD Nested classes) - $(YES1 class.html#nested) - ) - - $(TR - $(TD Inner (adaptor) classes) - $(YES1 class.html#nested) - ) - - $(TR - $(TD Covariant return types) - $(YES1 function.html) - ) - - $(TR - $(TD Properties) - $(YES1 property.html#classproperties) - ) - - $(TR -Performance | - ) - - $(TR - $(TD Inline assembler) - $(YES1 iasm.html) - ) - - $(TR - $(TD Direct access to hardware) - $(YES) - ) - - $(TR - $(TD Lightweight objects) - $(YES1 struct.html) - ) - - $(TR - $(TD Explicit memory allocation control) - $(YES1 memory.html) - ) - - $(TR - $(TD Independent of VM) - $(YES) - ) - - $(TR - $(TD Direct native code gen) - $(YES) - ) - - $(TR -Generic Programming | - ) - - $(TR - $(TD Class Templates) - $(YES1 template.html) - ) - - $(TR - $(TD Function Templates) - $(YES1 template.html) - ) - - $(TR - $(TD Implicit Function Template Instantiation) - $(YES1 template.html) - ) - - $(TR - $(TD Partial and Explicit Specialization) - $(YES1 template.html) - ) - - $(TR - $(TD Value Template Parameters) - $(YES1 template.html) - ) - - $(TR - $(TD Template Template Parameters) - $(YES1 template.html) - ) - - $(TR - $(TD Variadic Template Parameters) - $(YES1 template.html) - ) -$(V2 - $(TR - $(TD Template Constraints) - $(YES1 concepts.html) - ) -) - $(TR - $(TD Mixins) - $(YES1 template-mixin.html) - ) - - $(TR - $(TD static if) - $(YES1 version.html#staticif) - ) - - $(TR - $(TD is expressions) - $(YES1 expression.html#IsExpression) - ) - - $(TR - $(TD typeof) - $(YES1 declaration.html#Typeof) - ) - - $(TR - $(TD foreach) - $(YES1 statement.html#ForeachStatement) - ) - - $(TR - $(TD Implicit Type Inference) - $(YES1 declaration.html#AutoDeclaration) - ) - - $(TR -Reliability | - ) - - $(TR - $(TD Contract Programming) - $(YES1 dbc.html) - ) - - $(TR - $(TD Unit testing) - $(YES1 unittest.html) - ) - - $(TR - $(TD Static construction order) - $(YES1 module.html#staticorder) - ) - - $(TR - $(TD Guaranteed initialization) - $(YES1 statement.html#DeclarationStatement) - ) - - $(TR - $(TD RAII (automatic destructors)) - $(YES1 memory.html#raii) - ) - - $(TR - $(TD Exception handling) - $(YES1 statement.html#TryStatement) - ) - - $(TR - $(TD Scope guards) - $(YES1 statement.html#ScopeGuardStatement) - ) - - $(TR - $(TD try-catch-finally blocks) - $(YES1 statement.html#TryStatement) - ) - - $(TR - $(TD Thread synchronization primitives) - $(YES1 statement.html#SynchronizedStatement) - ) - - $(TR -Compatibility | - ) - - $(TR - $(TD C-style syntax) - $(YES) - ) - - $(TR - $(TD Enumerated types) - $(YES1 enum.html) - ) - - $(TR - $(TD Support all C types) - $(YES1 type.html) - ) - - $(TR - $(TD 80 bit floating point) - $(YES1 type.html) - ) - - $(TR - $(TD Complex and Imaginary) - $(YES1 type.html) - ) - - $(TR - $(TD Direct access to C) - $(YES1 attribute.html#linkage) - ) - - $(TR - $(TD Use existing debuggers) - $(YES) - ) - - $(TR - $(TD Struct member alignment control) - $(YES1 attribute.html#align) - ) - - $(TR - $(TD Generates standard object files) - $(YES) - ) - - $(TR - $(TD Macro text preprocessor) - $(NO1 pretod.html) - ) - - $(TR -Other | - ) - - $(TR - $(TD Conditional compilation) - $(YES1 version.html) - ) - - $(TR - $(TD Unicode source text) - $(YES1 lex.html) - ) - - $(TR - $(TD Documentation comments) - $(YES1 ddoc.html) - ) - - - -
|---|
-
-
-
- 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.
-
- -
- Implicit Type Inference -
- This refers to the ability to pick up the type of a
- declaration from its initializer.
-
- -
- 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.
- $(REDO 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: - $(I "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:
-$(CPPCODE
-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 -
- $(I 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.
-
- -
- Inner (adaptor) classes -
- A $(I nested class) is one whose definition is within the scope
- of another class. An $(I 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. - -
Overloading based on Constraints
- - $(P Given a list of overloaded templates with the same name, - constraints act as a yes/no filter to determine the list - of candidates for a match. - Overloading based on constraints can thus be achieved by - setting up constraint expressions that are mutually exclusive. - For example, overloading template $(CODE Foo) so that one - takes odd integers and the other even: - ) ---- -template Foo(int N) if (N & 1) { ... } // A -template Foo(int N) if (!(N & 1)) { ... } // B -... -Foo!(3) // instantiates A -Foo!(64) // instantiates B ---- - - $(P Constraints are not involved with determining which - template is more specialized than another. - ) - ---- -void foo(T, int N)() if (N & 1) { ... } // A -void foo(T : int, int N)() if (N > 3) { ... } // B -... -foo!(int, 7)(); // picks B, more specialized -foo!(int, 1)(); // picks A, as it fails B's constraint -foo!("a", 7)(); // picks A -foo!("a", 4)(); // error, no match ---- - -References
- - $(UL - $(LI $(LINK2 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2081.pdf, Concepts (Revision 1)) - by Douglas Gregor and Bjarne Stroustrup - ) - ) - -) - -Macros: - TITLE=Template Constraints - WIKI=Constraints -META_KEYWORDS=D Programming Language, constraints, template, concepts, C++ -META_DESCRIPTION=Going beyond type patterns to constrain template instantiations. - - - diff --git a/const-faq.dd b/const-faq.dd deleted file mode 100644 index a48fa24043..0000000000 --- a/const-faq.dd +++ /dev/null @@ -1,294 +0,0 @@ -Ddoc - -$(D_S const(FAQ), - - $(P D's $(D const)/$(D immutable) system is unique, and so there - are a lot of questions about it. ) - - $(UL - - $(ITEMR const, Why does D have const?) - $(ITEMR principles, What principles drove the D const design?) - $(ITEMR transitive-const, What is $(I transitive const)?) - $(ITEMR head-const, What is $(I head const)?) - $(ITEMR tail-const, What is $(I tail const)?) - $(ITEMR logical-const, What is $(I logical const)?) - $(ITEMR readonly, Why not use $(I readonly) to mean read only view?) - $(ITEMR java-const, Why did Java reject const?) - $(ITEMR cpp-const, How does const differ in C++?) - $(ITEMR invariant-strings, Why are strings immutable?) - $(ITEMR const-parameters, Why aren't function parameters const by default?) - $(ITEMR static-members, Are static class members covered by transitive const?) - $(ITEMR invariant, What is $(I immutable) good for?) - ) - -$(ITEM const, Why does D have const?) - - $(P People often express frustration with const and immutable - in D 2.0 and wonder if it is worth it. - ) - - $(OL - - $(LI It makes function interfaces more self-documenting. Without - transitive const, for all pointer/reference parameters one must rely on - the documentation (which is always missing, out of date, or wrong). Note - that without transitivity, C++ const is nearly useless for such - self-documentation, which is why C++ programmers tend to rely on - convention instead. - ) - - $(LI It makes for interfaces that can be relied upon, which becomes - increasingly important the more people that are involved with the code. - In other words, it scales very well. People who are involved with - projects with large teams of programmers say that lack of const - makes their lives difficult because they cannot rely on the compiler to - enforce convention. The larger the team, the worse it gets. Managing - APIs is critical to a large project - it's why BASIC doesn't scale (for - an extreme example). - ) - - $(LI Const transitivity makes for some interesting optimization - opportunities. The value of this has not been explored or exploited. - ) - - $(LI Here's the biggie. Points 1..3 are insignificant in comparison. The - future of programming will be multicore, multithreaded. Languages that - make it easy to program them will supplant languages that don't. - Transitive const is key to bringing D into this paradigm. The surge in - use of Haskell and Erlang is evidence of this coming trend (the killer - feature of those languages is they make it easy to do multiprogramming). - C++ cannot be retrofitted to supporting multiprogramming in a manner - that makes it accessible. D isn't there yet, but it will be, and - transitive const will be absolutely fundamental to making it work. - ) - ) - - $(P Of course, for writing single-threaded one man programs of - fairly modest size, const is not particularly useful. - And in D const can be effectively ignored by just not using it, or - by using D 1.0. The only place const is imposed is with the immutable - string type. - ) - -$(ITEM principles, What principles drove the D const design?) - - $(OL - $(LI It will be mathematically sound. That means there - are no legal escapes from it.) - $(LI Any type can be wrapped in a struct and the resulting - struct can still exhibit the same const behavior - in other - words, no magic behavior for certain types.) - $(LI Const behavior will be transitive.) - $(LI Const behavior for type T will be equivalent for all types T.) - ) - -$(ITEM transitive-const, What is $(I transitive const)?) - - $(P Transitive const means that once const is applied to a type, - it applies recursively to every sub-component of that type. Hence: - ) - ---- -const(int*)** p; -p += 1; // ok, p is mutable -*p += 1; // ok, *p is mutable -**p += 1; // error, **p is const -***p += 1; // error, ***p is const ---- - - $(P With transitivity, there is no way to have a - $(I const pointer to mutable int). - ) - - $(P C++ const is not transitive.) - -$(ITEM head-const, What is $(I head const)?) - - $(P Head const is where the const applies only to the component - of the type adjacent to the const. For example: - ) - ---- -headconst(int**) p; ---- - $(P would be read as p being a: $(I const pointer to mutable pointer - to mutable int.) D does not have head const (the $(CODE headconst) is - there just for illustrative purposes), but C++ const is - a head const system. - ) - -$(ITEM tail-const, What is $(I tail const)?) - - $(P Tail const is the complement of head const - everything reachable - from the const type is also const except for the top level. For - example: - ) - ---- -tailconst(int**) p; ---- - $(P would be read as p being a: $(I mutable pointer to const pointer - to const int.) Head const combined with tail const yields transitive - const. - D doesn't have $(CODE tailconst) (the keyword is there just for - illustrative purposes) as a distinct type constructor. - ) - -$(ITEM logical-const, What is $(I logical const)?) - - $(P $(I Logical const) refers to data that appears to be constant - to an observer, but is not actually const. An example would be - an object that does lazy evaluation:) - ---- -struct Foo { - mutable int len; - mutable bool len_done; - const char* str; - int length() - { if (!len_done) - { len = strlen(str); - len_done = true; - } - return len; - } - this(char* str) { this.str = str; } -} -const Foo f = Foo("hello"); -bar(f.length); ---- - - $(P The example evaluates $(CODE f.len) only if it is needed. - $(CODE Foo) is logically const, because to the observer of the object - its return values never change after construction. - The $(CODE mutable) qualifier says that even if an instance - of $(CODE Foo) is const, those fields can still change. - While C++ supports the notion of logical const, D does not, - and D does not have a $(CODE mutable) qualifier. - ) - - $(P The problem with logical const is that const is no longer - transitive. Not being transitive means there is the potential - for threading race conditions, and there is no way to determine - if an opaque const type has mutable members or not. - ) - - $(P Reference: - $(LINK2 http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter08_025.html, mutable: bitwise vs. logical const) - ) - -$(ITEM readonly, Why not use $(I readonly) to mean read only view?) - - $(P $(I Readonly) has a well established meaning in software to - mean ROM, or Read Only Memory that can never be changed. - For computers with hardware protection for memory pages, readonly - also means that the memory contents cannot be altered. - Using readonly in D to mean a read only view of memory that could - be altered by another alias or thread runs counter to this. - ) - -$(ITEM java-const, Why did Java reject const?) - - $(P $(LINK http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070) - ) - -$(ITEM cpp-const, How does const differ in C++?) - - $(P C++ has a const system that is closer to D's than any other - language, but it still has huge differences:) - - $(OL - $(LI const is not transitive) - $(LI no immutables) - $(LI const objects can have mutable members) - $(LI const can be legally cast away and the data modified) - $(LI $(CODE const T) and $(CODE T) are not always distinct types) - ) - -$(ITEM invariant-strings, Why are strings immutable?) - - $(P $(LINK2 http://drdobbs.com/blogs/architecture-and-design/228700475, Immutable Strings) - ) - -$(ITEM const-parameters, Why aren't function parameters const by default?) - - $(P Since most (nearly all?) function parameters will not be modified, - it would seem to make sense to make them all const by default, - and one would have to specifically mark as mutable those that would - be changed. The problems with this are: - ) - - $(OL - - $(LI It would be a huge break from past D practice, and practice - in C, C++, Java, C#, etc.) - $(LI It would require a new keyword, say $(CODE mutable).) - $(LI And worst, it would make declarations inconsistent: ---- -void foo(int* p) { - int* q; - ... -} ---- - $(CODE p) points to const, and $(CODE q) points to mutable. - This kind of inconsistency leads to all sorts of mistakes. - It also makes it very hard to write generic code that deals with - types. - ) - ) - - $(P Using $(CODE in) can mitigate the ugliness of having to annotate - with $(CODE const):) ---- -void str_replace(in char[] haystack, in char[] needle); ---- - -$(ITEM static-members, Are static class members covered by transitive const?) - - $(P A static class member is part of the global state of a program, - not part of the state of an object. Thus, a class having a mutable - static member does not violate the transitive constness of an object - of that class. - ) - -$(ITEM invariant, What is $(I immutable) good for?) - - $(P Immutable data, once initialized, is never changed. - This has many uses: - ) - - $(UL - $(LI Access to immutable data need not be synchronized - when multiple threads read it.) - $(LI Data races, tearing, sequential consistency, and - cache consistency are all non-issues when working with - immutable data.) - $(LI Pure functions can only accept immutable parameters.) - $(LI When doing a $(I deep copy) of a data structure, - the immutable portions need not be copied.) - $(LI Invariance allows a large chunk of data to be treated - as a value type even if it is passed around by reference - (strings are the most common case of this).) - $(LI Immutable type provides more self-documenting information - to the programmer.) - $(LI Immutable data can be placed in hardware protected read-only - memory, or even in ROMs.) - $(LI If immutable data does change, it is a sure sign of a memory - corruption bug, and it is possible to automatically check for - such data integrity.) - $(LI Immutable types provide for many program optimization - opportunities.) - ) - - $(P $(I const) acts as a bridge between the mutable and immutable - worlds, so a single function can be used to accept both types - of arguments.) -) - -Macros: - TITLE=const(FAQ) - WIKI=constFAQ - CATEGORY_FAQ=$0 - ITEMR=$(LI $(LINK2 #$1, $+)) - ITEM=$+
diff --git a/const3.dd b/const3.dd deleted file mode 100644 index c8d2b28ea9..0000000000 --- a/const3.dd +++ /dev/null @@ -1,592 +0,0 @@ -Ddoc - -$(D_S Const and Immutable, - - $(P When examining a data structure or interface, it is very - helpful to be able to easily tell which data can be expected to not - change, which data might change, and who may change that data. - This is done with the aid of the language typing system. - Data can be marked as const or immutable, with the default being - changeable (or $(I mutable)). - ) - - $(P $(I immutable) applies to data that cannot change. - Immutable data values, once constructed, remain the same for - the duration of the program's - execution. - Immutable data can be placed in ROM (Read Only Memory) or in - memory pages marked by the hardware as read only. - Since immutable data does not change, it enables many opportunities - for program optimization, and has applications in functional - style programming. - ) - - $(P $(I const) applies to data that cannot be changed by - the const reference to that data. It may, however, be changed - by another reference to that same data. - Const finds applications in passing data through interfaces - that promise not to modify them. - ) - - $(P Both immutable and const are $(I transitive), which means - that any data reachable through an immutable reference is also - immutable, and likewise for const. - ) - -$(SECTION2 Immutable Storage Class, - - $(P - The simplest immutable declarations use it as a storage class. - It can be used to declare manifest constants. - ) - ---- -immutable int x = 3; // x is set to 3 -x = 4; // error, x is immutable -char[x] s; // s is an array of 3 char's ---- - - $(P The type can be inferred from the initializer: - ) ---- -immutable y = 4; // y is of type int -y = 5; // error, y is immutable ---- - - $(P If the initializer is not present, the immutable can - be initialized from the corresponding constructor: - ) - ---- -immutable int z; -void test() { - z = 3; // error, z is immutable -} -static this() { - z = 3; // ok, can set immutable that doesn't - // have static initializer -} ---- - $(P - The initializer for a non-local immutable declaration must be - evaluatable - at compile time: - ) - ---- -int foo(int f) { return f * 3; } -int i = 5; -immutable x = 3 * 4; // ok, 12 -immutable y = i + 1; // error, cannot evaluate at compile time -immutable z = foo(2) + 1; // ok, foo(2) can be evaluated at compile time, 7 ---- - - $(P The initializer for a non-static local immutable declaration - is evaluated at run time: - ) ---- -int foo(int f) -{ - immutable x = f + 1; // evaluated at run time - x = 3; // error, x is immutable -} ---- - - $(P - Because immutable is transitive, data referred to by an immutable is - also immutable: - ) - ---- -immutable char[] s = "foo"; -s[0] = 'a'; // error, s refers to immutable data -s = "bar"; // error, s is immutable ---- - - $(P Immutable declarations can appear as lvalues, i.e. they can - have their address taken, and occupy storage. - ) -) - -$(SECTION2 Const Storage Class, - - $(P - A const declaration is exactly like an immutable declaration, - with the following differences: - ) - - $(UL - $(LI Any data referenced by the const declaration cannot be - changed from the const declaration, but it might be changed - by other references to the same data.) - - $(LI The type of a const declaration is itself const.) - ) - -$(COMMENT -$(TABLE1 - -$(TR $(TH ) $(TH AddrOf) $(TH CTFEInit) $(TH Static) $(TH Field) $(TH Stack) $(TH Ctor)) - -$(TR $(TD ) - $(TD Can the address be taken?) - $(TD Is compile time function evaluation done on the initializer?) - $(TD allocated as static data?) - $(TD allocated as a per-instance field?) - $(TD allocated on the stack?) - $(TD Can the variable be assigned to in a constructor?) -) - - -$(TR $(TH Global data)) - -$(TR $(TD1 const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) -$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) -$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) -$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) - - -$(TR $(TH Class Members)) - -$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(Y) $(N) $(Y)) -$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) -$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) -$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) - - -$(TR $(TH Local Variables)) - -$(TR $(TD1 const T x;) $(Y) $(Y) $(N) $(N) $(Y) $(N)) -$(TR $(TD1 const T x = 3;) $(Y) $(N) $(N) $(N) $(Y) $(N)) -$(TR $(TD1 static const T x;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) -$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) - -$(TR $(TH Function Parameters)) - -$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(N) $(Y) $(N)) -) - - -$(P Notes:) - -$(OL -$(LI If CTFEInit is true, then the initializer can also be used for -constant folding.) -) - - -$(TABLE1 -Removing Immutable With A Cast
- - $(P - The immutable type can be removed with a cast: - ) - ---- -immutable int* p = ...; -int* q = cast(int*)p; ---- - - $(P - This does not mean, however, that one can change the data: - ) - ---- -*q = 3; // allowed by compiler, but result is undefined behavior ---- - - $(P - The ability to cast away immutable-correctness is necessary in - some cases where the static typing is incorrect and not fixable, such - as when referencing code in a library one cannot change. - Casting is, as always, a blunt and effective instrument, and - when using it to cast away immutable-correctness, one must assume - the responsibility to ensure the immutableness of the data, as - the compiler will no longer be able to statically do so. - ) -) - - -$(SECTION2 Immutable Member Functions, - - $(P - Immutable member functions are guaranteed that the object - and anything referred to by the $(CODE this) reference is immutable. - They are declared as: - ) - ---- -struct S { - int x; - - void foo() immutable { - x = 4; // error, x is immutable - this.x = 4; // error, x is immutable - } -} ---- - $(P Note that using $(D_KEYWORD immutable) on the left hand side of a method does not apply to the return type: - ) - ---- -struct S { - immutable int[] bar() // bar is still immutable, return type is not! - { - } -} ---- - $(P To make the return type $(D_KEYWORD immutable), you need to surround the return type with parentheses: - ) - ---- -struct S { - immutable(int[]) bar() // bar is now mutable, return type is immutable. - { - } -} ---- - $(P To make both the return type and the method $(D_KEYWORD immutable), you can write: - ) ---- -struct S { - immutable(int[]) bar() immutable - { - } -} ---- -) - - -$(SECTION2 Const Type, - - $(P - Const types are like immutable types, except that const - forms a read-only $(I view) of data. Other aliases to that - same data may change it at any time. - ) -) - - -$(SECTION2 Const Member Functions, - - $(P - Const member functions are functions that are not allowed to - change any part of the object through the member function's - this reference. - ) -) - - -$(SECTION2 Implicit Conversions, - - $(P - Mutable and immutable types can be implicitly converted to const. - Mutable types cannot be implicitly converted to immutable, - and vice versa. - ) -) - - -$(SECTION2 Comparing D Immutable and Const with C++ Const, - -$0- CPPCODE2 =
$0- ERROR = $(RED $(B error)) - COMMA=, -META_KEYWORDS=D Programming Language, const, immutable -META_DESCRIPTION=Comparison of const between the -D programming language, C++, and C++0x - diff --git a/contributing.dd b/contributing.dd new file mode 100644 index 0000000000..67bf5fda4b --- /dev/null +++ b/contributing.dd @@ -0,0 +1,22 @@ +Ddoc + +$(D_S Contributing, + +$(NOTE To search the bug tracker or report issues, see $(LINK2 bugstats.html, Issues).) + +$(H2 $(LNAME2 github, GitHub Projects)) + +* $(LINK2 https://github.com/dlang, dlang) - dmd, phobos, dub, dlang.org etc +* $(LINK2 https://github.com/dlang-community, dlang-community) - dfmt, dscanner etc + + +$(H2 $(LNAME2 see-also, Getting Started)) + +* Please read: $(LINK2 https://github.com/dlang/dmd/blob/master/CONTRIBUTING.md#solving-bugs--submitting-pull-requests, + Solving bugs / Submitting pull requests) +* Get involved: $(HTTPS wiki.dlang.org/Get_involved) + +) + +Macros: + TITLE=Contributing diff --git a/cpp0x.dd b/cpp0x.dd deleted file mode 100644 index c53bcd6206..0000000000 --- a/cpp0x.dd +++ /dev/null @@ -1,737 +0,0 @@ -Ddoc - -$(COMMUNITY D and C++0x, - - - $(P - C++ is undergoing an upgrade to a new standard, commonly referred - to as C++0x. - This article covers the highlights of - $(LINK2 $(NDOCS)2008/n2597.html, C++0x core language changes) - and compares them with what is available in D. - Since C++0x is far from being finalized, - this article is subject to being obsoleted by new proposals and - revisions to existing ones. - C++0x standard library changes are not addressed here. - TBD means To Be Determined. - ) - -$(SECTION3 Proposed C++0x Features, - - $(UL - $(LI $(LINK2 #rvalue-reference, A Proposal to Add an Rvalue Reference to the C++ Language)) - $(LI $(LINK2 #class-rvalue, Clarification of Initialization of Class Objects by rvalues)) - $(LI $(LINK2 #move-semantics, Extending Move Semantics To *this (Revision 2))) - $(LI $(LINK2 #static-assert, static_assert)) - $(LI $(LINK2 #template-aliases, Template aliases for C++)) - $(LI $(LINK2 #extern-template, Extern template)) - $(LI $(LINK2 #variadic-templates, Variadic Templates)) - $(LI $(LINK2 #variadic-template-templates, Extending Variadic Template Template Parameters)) - $(LI $(LINK2 #nullptr, A name for the null pointer: nullptr)) - $(LI $(LINK2 #strong-enums, Strongly Typed Enums)) - $(LI $(LINK2 #extended-friends, Extended friend Declarations)) - $(LI $(LINK2 #constant-expressions, Generalized Constant Expressions)) - $(LI $(LINK2 #namespace-association, Namespace Association ("Strong Using"))) - $(LI $(LINK2 #c99-preprocessor, Synchronizing the C++ preprocessor with C99)) - $(LI $(LINK2 #alignment, Adding Alignment Support to the C++ Programming Language)) - $(LI $(LINK2 #conditional, Conditionally-Supported Behavior)) - $(LI $(LINK2 #undefined-behavior, Changing Undefined Behavior into Diagnosable Errors)) - $(LI $(LINK2 #long-long, Adding the long long type to C++)) - $(LI $(LINK2 #extended-integer-types, Adding extended integer types to C++)) - $(LI $(LINK2 #delegating-ctors, Delegating Constructors)) - $(LI $(LINK2 #explicit-conversion, Explicit Conversion Operators)) - $(LI $(LINK2 #char16_t, New Character Types in C++)) - $(LI $(LINK2 #right-angle-brackets, Right Angle Brackets)) - $(LI $(LINK2 #type-deduction, Deducing the type of variable from its initializer expression)) - $(LI $(LINK2 #auto-declarations, The Syntax of auto Declarations)) - $(LI $(LINK2 #inheriting-ctors, Inheriting Constructors)) - $(LI $(LINK2 #sequence-points, A finer-grained alternative to sequence points)) - $(LI $(LINK2 #lambda, (monomorphic) Lambda expressions and closures for C++)) - $(LI $(LINK2 #__func__, Proposed addition of __func__ predefined identifier from C99)) - $(LI $(LINK2 #atomic, Atomic operations with multi-threaded environments)) - $(LI $(LINK2 #concurrency, Sequencing and the concurrency memory model)) - $(LI $(LINK2 #raw-strings, Raw String Literals)) - $(LI $(LINK2 #pod, PODs unstrung)) - $(LI $(LINK2 #exceptions, Propagating exceptions when joining threads)) - $(LI $(LINK2 #decltype, Decltype)) - $(LI $(LINK2 #sizeof, Extending sizeof)) - $(LI $(LINK2 #utf8-literals, UTF8 Literals)) - $(LI $(LINK2 #ucs-in-literals, Universal Character Names in Literals)) - $(LI $(LINK2 #defaulted, Defaulted and Deleted Functions)) - $(LI $(LINK2 #unions, Unrestricted Unions)) - $(LI $(LINK2 #library, A Multi-threading Library for Standard C++)) - $(LI $(LINK2 #abandoning, Abandoning a Process)) - $(LI $(LINK2 #return-types, New function declaration syntax for deduced return types)) - $(LI $(LINK2 #atomic-signals, Allow atomics use in signal handlers)) - ) - - $(UL - $(LI $(LINK2 #local-classes, Making Local Classes more Useful)) - $(LI $(LINK2 #initializer-lists, Initializer lists)) - $(LI $(LINK2 #thread-local-storage, Thread-Local Storage)) - $(LI $(LINK2 #member-initializers, Member Initializers)) - $(LI $(LINK2 #concepts, Concepts (unified proposal))) - $(LI $(LINK2 #for-loop, Proposal for new for-loop)) - $(LI $(LINK2 #general-attributes, General Attributes for C++)) - ) - - $(UL - $(LI $(LINK2 #extensible-literals, Extensible Literals)) - $(LI $(LINK2 #dynamic-concurrency, Dynamic initialization and concurrency)) - $(LI $(LINK2 #garbage-collection, Minimal Support for Garbage Collection and Reachability-Based Leak Detection)) - $(LI $(LINK2 #forward-enums, Forward declaration of enumerations)) - ) -) - -$(SECTION3 $(LNAME2 rvalue-reference, A Proposal to Add an Rvalue Reference to the C++ Language), - - $(P $(LINK2 $(NDOCS)2005/n1770.html, N1770): TBD - ) - -) - -$(SECTION3 $(LNAME2 class-rvalue, Clarification of Initialization of Class Objects by rvalues), - - $(P $(LINK2 $(NDOCS)2004/n1610.html, N1610): TBD - ) - -) - -$(SECTION3 $(LNAME2 move-semantics, Extending Move Semantics To *this (Revision 2)), - - $(P $(LINK2 $(NDOCS)2007/n2439.htm, N2439): TBD - ) - -) - -$(SECTION3 $(LNAME2 static-assert, static_assert), - - $(P $(LINK2 $(NDOCS)2004/n1720.html, N1720): - $(LINK2 version.html#StaticAssert, static assert) is - part of D. - ) - -) - -$(SECTION3 $(LNAME2 template-aliases, Template aliases for C++), - - $(P $(LINK2 $(NDOCS)2007/n2258.pdf, N2258): - Both $(LINK2 template.html, templates and template instantiations) - can be $(LINK2 declaration.html#alias, aliased): - ) ---- -struct S(T) { T int; } -alias S X; // alias template -alias S!(int) Y; // alias template instantiation -X!(int) x; -Y y; // x and y are the same type ---- -) - -$(SECTION3 $(LNAME2 extern-template, Extern template), - - $(P $(LINK2 $(NDOCS)2006/n1987.htm, N1987): - This is a workaround for problems in the traditional compile/link - build model. - The D compiler deals with this by if multiple modules are compiled - at the same time, only one instance of a template is generated - for all the generated object files rather than one instance in each - object file. Further improvements are planned for generating library - modules that avoid multiple redundant template instantiations. - ) - -) - -$(SECTION3 $(LNAME2 variadic-templates, Variadic Templates), - - $(P $(LINK2 $(NDOCS)2007/n2242.pdf, N2242): - D's $(LINK2 template.html#variadic-templates, variadic templates). - ) - -) - -$(SECTION3 $(LNAME2 variadic-template-templates, Extending Variadic Template Template Parameters), - - $(P $(LINK2 $(NDOCS)2008/n2555.pdf, N2555): TBD - ) - -) - -$(SECTION3 $(LNAME2 nullptr, A name for the null pointer: nullptr), - - $(P $(LINK2 $(NDOCS)2007/n2431.pdf, N2431): - D has the $(LINK2 expression.html#null, null) equivalent. - ) - -) - -$(SECTION3 $(LNAME2 strong-enums, Strongly Typed Enums), - - $(P $(LINK2 $(NDOCS)2007/n2347.pdf, N2347): - D $(LINK2 enum.html, enums) are: - ) - - $(OL - $(LI Comparisons between different enum types should be an error, - but is not: ---- -void main() { - enum Color { ClrRed, ClrOrange, ClrYellow, ClrGreen, ClrBlue, ClrViolet }; - enum Alert { CndGreen, CndYellow, CndRed }; - Color c = Color.ClrRed; - Alert a = Alert.CndGreen; - a = c; // error - a = Color.ClrYellow; // error - bool armWeapons = ( a >= Color.ClrYellow ); // ok; oops -} ---- - ) - $(LI The underlying type can be specified.) - $(LI Named enums are strongly scoped. Anonymous enum members are - declared in the enclosing scope.) - $(LI Explicit qualification is needed to specify a named enum - member.) - ) - -) - -$(SECTION3 $(LNAME2 extended-friends, Extended friend Declarations), - - $(P $(LINK2 $(NDOCS)2005/n1791.pdf, N1791): - All code in a module has - $(LINK2 attribute.html#ProtectionAttribute, access) - to private members - of any struct or class declared in that module that is in - scope. - Package protected members can be accessed by any code in the - same package. - There is no need in D to have friend declarations or - complex lookup rules for them. - ) - -) - -$(SECTION3 $(LNAME2 constant-expressions, Generalized Constant Expressions), - - $(P $(LINK2 $(NDOCS)2007/n2235.pdf, N2235): - D has $(LINK2 function.html#interpretation, compile time function execution) - (CTFE). CTFE is much more flexible, as functions to be evaluated - at compile time: - ) - - $(OL - $(LI do not require a special keyword (C++0x requires $(CODE constexpr))) - $(LI can have multiple statements in the function) - $(LI can be recursive) - $(LI can modify local variables) - $(LI can have out parameters) - ) - -) - -$(SECTION3 $(LNAME2 namespace-association, Namespace Association ("Strong Using")), - - $(P $(LINK2 $(NDOCS)2008/n2535.html, N2535): - D doesn't have namespaces, - so this is irrelevant. - ) - -) - -$(SECTION3 $(LNAME2 c99-preprocessor, Synchronizing the C++ preprocessor with C99), - - $(P $(LINK2 $(NDOCS)2004/n1653.htm, N1653): - D does not have a preprocessor, - so this is not relevant to D. - ) - -) - -$(SECTION3 $(LNAME2 alignment, Adding Alignment Support to the C++ Programming Language), - - $(P $(LINK2 $(NDOCS)2007/n2341.pdf, N2341): - D has the $(LINK2 attribute.html#align, align) - attribute to specify the alignment - of declarations, and the $(LINK2 property.html#alignof, .alignof) - property to - determine the alignment size of an expression or type. - ) - -) - -$(SECTION3 $(LNAME2 conditional, Conditionally-Supported Behavior), - - $(P $(LINK2 $(NDOCS)2004/n1627.pdf, N1627): - There are some allowed vendor specific behaviors in D, - such as $(LINK2 pragma.html, pragmas). - ) - -) - -$(SECTION3 $(LNAME2 undefined-behavior, Changing Undefined Behavior into Diagnosable Errors), - - $(P $(LINK2 $(NDOCS)2004/n1727.pdf, N1727): - D does not have undefined behavior with integer literal types, - character escapes, or passing non-POD objects to ellipses. - ) - -) - -$(SECTION3 $(LNAME2 long-long, Adding the long long type to C++), - - $(P $(LINK2 $(NDOCS)2005/n1811.pdf, N1811): - D's $(LINK2 type.html, long) type is equivalent. - ) - -) - -$(SECTION3 $(LNAME2 extended-integer-types, Adding extended integer types to C++), - - $(P $(LINK2 $(NDOCS)2006/n1988.pdf, N1988): - D has the $(LINK2 type.html, cent and - ucent) types for - 128 bit integral types (not implemented in dmd or gdc). - There is no proposal for other extended - integral types, but it's hard to imagine a justification for - adding more to the core language. - ) - -) - -$(SECTION3 $(LNAME2 delegating-ctors, Delegating Constructors), - - $(P $(LINK2 $(NDOCS)2006/n1986.pdf, N1986): - D has - $(LINK2 class.html#delegating-constructors, delegating constructors). - ) - -) - -$(SECTION3 $(LNAME2 explicit-conversion, Explicit Conversion Operators), - - $(P $(LINK2 $(NDOCS)2007/n2437.html, N2437): TBD - ) - -) - -$(SECTION3 $(LNAME2 char16_t, New Character Types in C++), - - $(P $(LINK2 $(NDOCS)2007/n2249.html, N2249): - C++0x adds new character types char16_t and char32_t, - which are equivalent to D's $(LINK2 type.html, wchar and dchar types). - The u and U character literal prefixes are equivalent to the - D $(LINK2 lex.html#StringLiteral, w and d postfixes). - ) - -) - -$(SECTION3 $(LNAME2 right-angle-brackets, Right Angle Brackets), - - $(P $(LINK2 $(NDOCS)2005/n1757.html, N1757): - Since D uses !( ) to instantiate templates rather than - < >, there are no parsing ambiguities and - no fixes are necessary. - ) - -) - -$(SECTION3 $(LNAME2 type-deduction, Deducing the type of variable from its initializer expression), - - $(P $(LINK2 $(NDOCS)2006/n1984.pdf, N1984): - D has $(LINK2 declaration.html#AutoDeclaration, type inference) - from initializers. - ) - -) - -$(SECTION3 $(LNAME2 auto-declarations, The Syntax of auto Declarations), - - $(P $(LINK2 $(NDOCS)2008/n2546.html, N2546): - D $(LINK2 attribute.html#auto, auto declarations) - do not have syntactic issues. - ) - -) - -$(SECTION3 $(LNAME2 inheriting-ctors, Inheriting Constructors), - - $(P $(LINK2 $(NDOCS)2008/n2540.html, N2540): TBD - ) - -) - -$(SECTION3 $(LNAME2 sequence-points, A finer-grained alternative to sequence points), - - $(P $(LINK2 $(NDOCS)2007/n2239.htm, N2239): TBD - ) - -) - -$(SECTION3 $(LNAME2 lambda, (monomorphic) Lambda expressions and closures for C++), - - $(P $(LINK2 $(NDOCS)2008/n2550.pdf, N2550): - D has $(GLINK2 expression, FunctionLiteral)s (lambda expressions) and - $(LINK2 function.html#closures, closures). - ) - -) - -$(SECTION3 $(LNAME2 __func__, Proposed addition of __func__ predefined identifier from C99), - - $(P $(LINK2 $(NDOCS)2007/n2340.html, N2340): TBD - ) - -) - -$(SECTION3 $(LNAME2 atomic, Atomic operations with multi-threaded environments), - - $(P $(LINK2 $(NDOCS)2007/n2427.html, N2427): TBD - ) - -) - -$(SECTION3 $(LNAME2 concurrency, Sequencing and the concurrency memory model), - - $(P $(LINK2 $(NDOCS)2007/n2429.htm, N2429): TBD - ) - -) - -$(SECTION3 $(LNAME2 raw-strings, Raw String Literals), - - $(P $(LINK2 $(NDOCS)2007/n2442.html, N2442): - D has $(LINK2 lex.html#StringLiteral, wysiwyg and delimited strings), - and all strings are Unicode. - ) - -) - -$(SECTION3 $(LNAME2 pod, PODs unstrung), - - $(P $(LINK2 $(NDOCS)2007/n2294.html, N2294): - All D $(LINK2 struct.html, structs) are - $(LINK2 glossary.html#pod, POD (Plain Old Data)). - D $(LINK2 class.html, classes) are reference, polymorphic types. - ) - -) - -$(SECTION3 $(LNAME2 exceptions, Propagating exceptions when joining threads), - - $(P $(LINK2 $(NDOCS)2007/n2179.html, N2179): TBD - ) - -) - -$(SECTION3 $(LNAME2 decltype, Decltype), - - $(P $(LINK2 $(NDOCS)2007/n2343.pdf, N2343): - The equivalent D construct is $(LINK2 declaration.html#typeof, typeof). - ) - -) - -$(SECTION3 $(LNAME2 sizeof, Extending sizeof), - - $(P $(LINK2 $(NDOCS)2007/n2253.html, N2253): - Using $(LINK2 property.html#sizeof, sizeof) without a $(I this) object: ---- -struct S { - int a; - static int foo() { - return a.sizeof; - } -} - -void test() { - int x = S.a.sizeof; -} ---- - works correctly in D. - ) - -) - -$(SECTION3 $(LNAME2 utf8-literals, UTF-8 Literals), - - $(P $(LINK2 $(NDOCS)2007/n2442.html, N2442): - $(LINK2 lex.html#StringLiteral, Char string literals) - are in UTF-8 format. - ) - -) - -$(SECTION3 $(LNAME2 ucs-in-literals, Universal Character Names in Literals), - - $(P $(LINK2 $(NDOCS)2007/n2170.html, N2170): - All Unicode characters are allowed in - $(LINK2 lex.html#StringLiteral, string literals). - Surrogate pair halves are not allowed unless hex literal notation - is used. - ) - -) - -$(SECTION3 $(LNAME2 defaulted, Defaulted and Deleted Functions), - - $(P $(LINK2 $(NDOCS)2007/n2326.html#delete, N2326): - D alows individual functions to be marked as $(LINK2 attribute.html#disable, disabled). - ) - -) - - -$(SECTION3 $(LNAME2 unions, Unrestricted Unions), - - $(P $(LINK2 $(NDOCS)2008/n2544.pdf, N2544): TBD - ) - -) - -$(SECTION3 $(LNAME2 library, A Multi-threading Library for Standard C++), - - $(P $(LINK2 $(NDOCS)2007/n2447.html, N2447): TBD - ) - -) - -$(SECTION3 $(LNAME2 abandoning, Abandoning a Process), - - $(P $(LINK2 $(NDOCS)2007/n2440.html, N2440): TBD - ) - -) - -$(SECTION3 $(LNAME2 return-types, New function declaration syntax for deduced return types), - - $(P $(LINK2 $(NDOCS)2007/n2445.html, N2445): TBD - ) - -) - -$(SECTION3 $(LNAME2 atomic-signals, Allow atomics use in signal handlers), - - $(P $(LINK2 $(NDOCS)2008/n2547.htm, N2547): TBD - ) - -) - -$(SECTION3 $(LNAME2 local-classes, Making Local Classes more Useful), - - $(P $(LINK2 $(NDOCS)2007/n2402.pdf, N2402): - D has no restrictions on using local classes as template - parameters. - ) - -) - -$(SECTION3 $(LNAME2 initializer-lists, Initializer lists), - - $(P $(LINK2 $(NDOCS)2008/n2531.pdf, N2531): - D has - $(LINK2 struct.html#StructLiteral, struct literals), - $(LINK2 expression.html#ArrayLiteral, array literals), - and $(LINK2 expression.html#AssocArrayLiteral, associative array literals). - ) - -) - -$(SECTION3 $(LNAME2 thread-local-storage, Thread-Local Storage), - - $(P $(LINK2 $(NDOCS)2007/n2280.html, N2280): - Thread-local storage is the default for statics and globals - in D. Thread-global storage is done by using the - $(LINK2 migrate-to-shared.html, $(B shared)) - storage class. - ) - -) - -$(SECTION3 $(LNAME2 member-initializers, Member Initializers), - - $(P $(LINK2 $(NDOCS)2007/n2426.htm, N2426): - D has - $(LINK2 class.html#class-default-initializer, member initializers), - which are called $(I default initializers). - ) - -) - -$(SECTION3 $(LNAME2 concepts, Concepts (unified proposal)), - - $(P $(LINK2 $(NDOCS)2006/n2081.pdf, N2081): - The D equivalent of C++ concepts are $(LINK2 concepts.html, constraints). - (As of $(LINK2 http://www.ddj.com/cpp/218600111, July 2009), - Concepts have been dropped from C++0x.) - ) - - $(TABLE2 Concepts and Constraints, - - $(TR - $(TH Description) - $(TH D Constraints) - $(TH C++0x Concepts) - ) - - $(TR - $(TD Overloading based on concepts/constraints) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Concepts/constraints on template type parameters) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Concepts/constraints on template value parameters) - $(TD Yes) - $(TD No) - ) - - $(TR - $(TD Concepts/constraints on template template/alias parameters) - $(TD Yes) - $(TD No) - ) - - $(TR - $(TD Composition and refinement of concepts/constraints) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Multi-type concepts/constraints) - $(TD Yes) - $(TD Yes) - ) - - $(TR - $(TD Expression of concepts/constraints) - $(TD Done with compile time expressions) - $(TD Done by enumeration of function signatures) - ) - - $(TR - $(TD Axioms) - $(TD Yes (as static asserts and function preconditions)) - $(TD Yes) - ) - - $(TR - $(TD new keywords) - $(TD No) - $(TD Yes: where, concept, concept_map, axiom, late_check) - ) - - $(TR - $(TD Semantic analysis of template bodies) - $(TD Lazy (done at instantiation time)) - $(TD Eager (done at definition time)) - ) - - $(TR - $(TD Template body checked against concept/constraint) - $(TD No) - $(TD Yes) - ) - - $(TR - $(TD Concept maps) - $(TD No (but could be done with proxy objects)) - $(TD Yes) - ) - - $(TR - $(TD All operations on constrained types must be specified in - concept/constraint) - $(TD No) - $(TD Yes) - ) - - $(TR - $(TD Complexity) - $(TD $(CODE if (expression)) added to template grammar) - $(TD quite a bit of new grammar and semantics added) - ) - - - ) - -) - -$(SECTION3 $(LNAME2 for-loop, Proposal for new for-loop), - - $(P $(LINK2 $(NDOCS)2007/n2394.html, N2394): - This is equivalent to the D - $(LINK2 statement.html#ForeachRangeStatement, $(I ForeachRangeStatement)). - ) - -) - -$(SECTION3 $(LNAME2 general-attributes, General Attributes for C++), - - $(P $(LINK2 $(NDOCS)2007/n2418.pdf, N2418): - Vendor specific attributes can be applied to statements - and declarations with - $(LINK2 pragma.html, pragmas). - ) - -) - -$(SECTION3 $(LNAME2 extensible-literals, Extensible Literals), - - $(P $(LINK2 $(NDOCS)2007/n2378.pdf, N2378): - D does not have user extensible literals. - ) - -) - -$(SECTION3 $(LNAME2 dynamic-concurrency, Dynamic initialization and concurrency), - - $(P $(LINK2 $(NDOCS)2008/n2513.html, N2513): TBD - ) - -) - -$(SECTION3 $(LNAME2 garbage-collection, Minimal Support for Garbage Collection and Reachability-Based Leak Detection), - - $(P $(LINK2 $(NDOCS)2008/n2527.html, N2527): - Garbage collection is optional in C++0x, - D $(LINK2 garbage.html, requires it). - The problem with an optional garbage collector is that in order - to write general purpose libraries, one must assume that there is - no garbage collector, therefore none of the productivity enhancing - advantages of it are available. - ) - -) - -$(SECTION3 $(LNAME2 forward-enums, Forward declaration of enumerations), - - $(P $(LINK2 $(NDOCS)2008/n2499.pdf, N2499): - Forward declarations are not necessary in D, as all declarations - are resolved essentially in parallel. - Incomplete $(LINK2 enum.html, enum) types, however, are possible: - ) ---- -enum E : int; ---- - $(P where the member values are hidden from the user. - ) - -) - -) - -Macros: - TITLE=D and C++0x - WIKI=Cpp0x - DOLLAR=$ - NDOCS=http://www.open-std.org/jtc1/sc22/wg21/docs/papers/ - FOO= - - diff --git a/cpp_interface.dd b/cpp_interface.dd deleted file mode 100644 index 2cb6b17a93..0000000000 --- a/cpp_interface.dd +++ /dev/null @@ -1,605 +0,0 @@ -Ddoc - -$(SPEC_S Interfacing to C++, - - $(P - While D is fully capable of - $(DDLINK interfaceToC, Interfacing to C, interfacing to C), - its ability to interface to C++ is much more limited. - There are three ways to do it: - ) - - $(OL - - $(LI Use C++'s ability to create a C interface, and then - use D's ability to - $(DDLINK interfaceToC, Interfacing to C, interface with C) - to access that interface. - ) - - $(LI Use C++'s ability to create a COM interface, and then - use D's ability to - $(DPLLINK COM.html, interface with COM) - to access that interface. - ) - - $(LI Use the limited ability described here to connect - directly to C++ functions and classes. - ) - - ) - -
The General Idea
- - $(P Being 100% compatible with C++ means more or less adding - a fully functional C++ compiler front end to D. - Anecdotal evidence suggests that writing such is a minimum - of a 10 man-year project, essentially making a D compiler - with such capability unimplementable. - Other languages looking to hook up to C++ face the same - problem, and the solutions have been: - ) - - $(OL - $(LI Support the COM interface (but that only works for Windows).) - $(LI Laboriously construct a C wrapper around - the C++ code.) - $(LI Use an automated tool such as SWIG to construct a - C wrapper.) - $(LI Reimplement the C++ code in the other language.) - $(LI Give up.) - ) - - $(P D takes a pragmatic approach that assumes a couple - modest accommodations can solve a significant chunk of - the problem: - ) - - $(UL - $(LI matching C++ name mangling conventions) - $(LI matching C++ function calling conventions) - $(LI matching C++ virtual function table layout for single inheritance) - ) - -Calling C++ Global Functions From D
- - $(P Given a C++ function in a C++ source file:) - -$(CPPCODE -#include <iostream> - -using namespace std; - -int foo(int i, int j, int k) { - cout << "i = " << i << endl; - cout << "j = " << j << endl; - cout << "k = " << k << endl; - - return 7; -} -) - - $(P In the corresponding D code, $(CODE foo) - is declared as having C++ linkage and function calling conventions: - ) - ------- -extern (C++) int foo(int i, int j, int k); ------- - - $(P and then it can be called within the D code:) - ------- -extern (C++) int foo(int i, int j, int k); - -void main() { - foo(1,2,3); -} ------- - - $(P Compiling the two files, the first with a C++ compiler, - the second with a D compiler, linking them together, - and then running it yields:) - -$(CONSOLE -i = 1 -j = 2 -k = 3 -) - - $(P There are several things going on here:) - - $(UL - $(LI D understands how C++ function names are "mangled" and the - correct C++ function call/return sequence.) - - $(LI Because modules are not part of C++, each function with - C++ linkage must be globally unique within the program.) - - $(LI There are no __cdecl, __far, __stdcall, __declspec, or other - such nonstandard C++ extensions in D.) - - $(LI There are no volatile type modifiers in D.) - - $(LI Strings are not 0 terminated in D. See "Data Type Compatibility" - for more information about this. However, string literals in D are - 0 terminated.) - - ) - - $(P C++ functions that reside in namespaces cannot be - direcly called from D. - ) - - -Calling Global D Functions From C++
- - $(P To make a D function accessible from C++, give it - C++ linkage:) - ---- -import std.stdio; - -extern (C++) int foo(int i, int j, int k) { - writefln("i = %s", i); - writefln("j = %s", j); - writefln("k = %s", k); - return 1; -} - -extern (C++) void bar(); - -void main() { - bar(); -} ---- - - $(P The C++ end looks like:) - -$(CPPCODE -int foo(int i, int j, int k); - -void bar() { - foo(6, 7, 8); -} -) - - $(P Compiling, linking, and running produces the output:) - -$(CONSOLE -i = 6 -j = 7 -k = 8 -) - - -Classes
- - $(P D classes are singly rooted by Object, and have an - incompatible layout from C++ classes. - D interfaces, however, are very similar to C++ single - inheritance class heirarchies. - So, a D interface with the attribute of $(CODE extern (C++)) - will have a virtual function pointer table (vtbl[]) that - exactly matches C++'s. - A regular D interface has a vtbl[] that differs in that - the first entry in the vtbl[] is a pointer to D's RTTI info, - whereas in C++ the first entry points to the first virtual - function. - ) - -Calling C++ Virtual Functions From D
- - $(P Given C++ source code defining a class like:) - -$(CPPCODE -#include <iostream> - -using namespace std; - -class D { - public: - virtual int bar(int i, int j, int k) - { - cout << "i = " << i << endl; - cout << "j = " << j << endl; - cout << "k = " << k << endl; - return 8; - } -}; - -D *getD() { - D *d = new D(); - return d; -} -) - - $(P We can get at it from D code like:) - ---- -extern (C++) { - interface D { - int bar(int i, int j, int k); - } - - D getD(); -} - -void main() { - D d = getD(); - d.bar(9,10,11); -} ---- - -Calling D Virtual Functions From C++
- - $(P Given D code like:) - ---- -extern (C++) int callE(E); - -extern (C++) interface E { - int bar(int i, int j, int k); -} - -class F : E { - extern (C++) int bar(int i, int j, int k) - { - writefln("i = ", i); - writefln("j = ", j); - writefln("k = ", k); - return 8; - } -} - -void main() { - F f = new F(); - callE(f); -} ---- - - $(P The C++ code to access it looks like:) - -$(CPPCODE -class E { - public: - virtual int bar(int i, int j, int k); -}; - - -int callE(E *e) { - return e->bar(11,12,13); -} -) - - $(P Note:) - - $(UL - $(LI non-virtual functions, and static member functions, - cannot be accessed.) - - $(LI class fields can only be accessed via virtual getter - and setter methods.) - ) - -Function Overloading
- - $(P C++ and D follow different rules for function overloading. - D source code, even when calling $(CODE extern (C++)) functions, - will still follow D overloading rules. - ) - - -Storage Allocation
- - $(P C++ code explicitly manages memory with calls to - $(CODE ::operator new()) and $(CODE ::operator delete()). - D allocates memory using the D garbage collector, - so no explicit delete's are necessary. - D's new and delete are not compatible with C++'s - $(CODE ::operator new) and $(CODE::operator delete). - Attempting to allocate memory with C++ $(CODE ::operator new) - and deallocate it with D's $(CODE delete), or vice versa, will - result in miserable failure. - ) - - $(P D can still explicitly allocate memory using std.c.stdlib.malloc() - and std.c.stdlib.free(), these are useful for connecting to C++ - functions that expect malloc'd buffers, etc. - ) - - $(P If pointers to D garbage collector allocated memory are passed to - C++ functions, it's critical to ensure that that memory will not - be collected by the garbage collector before the C++ function is - done with it. This is accomplished by: - ) - - $(UL - - $(LI Making a copy of the data using std.c.stdlib.malloc() and passing - the copy instead.) - - $(LI Leaving a pointer to it on the stack (as a parameter or - automatic variable), as the garbage collector will scan the stack.) - - $(LI Leaving a pointer to it in the static data segment, as the - garbage collector will scan the static data segment.) - - $(LI Registering the pointer with the garbage collector with the - std.gc.addRoot() or std.gc.addRange() calls.) - - ) - - $(P An interior pointer to the allocated memory block is sufficient - to let the GC - know the object is in use; i.e. it is not necessary to maintain - a pointer to the beginning of the allocated memory. - ) - - $(P The garbage collector does not scan the stacks of threads not - created by the D Thread interface. Nor does it scan the data - segments of other DLL's, etc. - ) - -Data Type Compatibility
- - $(TABLE2 D And C Type Equivalence, - - $(TR - $(TH D type) - $(TH C type) - ) - - $(TR - $(TD $(B void)) - $(TD $(B void)) - ) - - $(TR - $(TD $(B byte)) - $(TD $(B signed char)) - ) - - $(TR - $(TD $(B ubyte)) - $(TD $(B unsigned char)) - ) - - $(TR - $(TD $(B char)) - $(TD $(B char) (chars are unsigned in D)) - ) - - $(TR - $(TD $(B wchar)) - $(TD $(B wchar_t) (when sizeof(wchar_t) is 2)) - ) - - $(TR - $(TD $(B dchar)) - $(TD $(B wchar_t) (when sizeof(wchar_t) is 4)) - ) - - $(TR - $(TD $(B short)) - $(TD $(B short)) - ) - - $(TR - $(TD $(B ushort)) - $(TD $(B unsigned short)) - ) - - $(TR - $(TD $(B int)) - $(TD $(B int)) - ) - - $(TR - $(TD $(B uint)) - $(TD $(B unsigned)) - ) - - $(TR - $(TD $(B long)) - $(TD $(B long long)) - ) - - $(TR - $(TD $(B ulong)) - $(TD $(B unsigned long long)) - ) - - $(TR - $(TD $(B float)) - $(TD $(B float)) - ) - - $(TR - $(TD $(B double)) - $(TD $(B double)) - ) - - $(TR - $(TD $(B real)) - $(TD $(B long double)) - ) - - $(TR - $(TD $(B ifloat)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B idouble)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B ireal)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B cfloat)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B cdouble)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B creal)) - $(TD no equivalent) - ) - - $(TR - $(TD $(B struct)) - $(TD $(B struct)) - ) - - $(TR - $(TD $(B union)) - $(TD $(B union)) - ) - - $(TR - $(TD $(B enum)) - $(TD $(B enum)) - ) - - $(TR - $(TD $(B class)) - $(TD no equivalent) - ) - - $(TR - $(TD $(I type)$(B *)) - $(TD $(I type) $(B *)) - ) - - $(TR - $(TD no equivalent) - $(TD $(I type) $(B &)) - ) - - $(TR - $(TD $(I type)$(B [)$(I dim)$(B ])) - $(TD $(I type)$(B [)$(I dim)$(B ])) - ) - - $(TR - $(TD $(I type)$(B [)$(I dim)$(B ]*)) - $(TD $(I type)$(B (*)[)$(I dim)$(B ])) - ) - - $(TR - $(TD $(I type)$(B [])) - $(TD no equivalent) - ) - - $(TR - $(TD $(I type)$(B [)$(I type)$(B ])) - $(TD no equivalent) - ) - - $(TR - $(TD $(I type) $(B function)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - $(TD $(I type)$(B (*))$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - ) - - $(TR - $(TD $(I type) $(B delegate)$(B $(LPAREN))$(I parameters)$(B $(RPAREN))) - $(TD no equivalent) - ) - - ) - - $(P These equivalents hold for most 32 bit C++ compilers. - The C++ standard - does not pin down the sizes of the types, so some care is needed. - ) - -Structs and Unions
- - $(P D structs and unions are analogous to C's. - ) - - $(P C code often adjusts the alignment and packing of struct members - with a command line switch or with various implementation specific - #pragma's. D supports explicit alignment attributes that correspond - to the C compiler's rules. Check what alignment the C code is using, - and explicitly set it for the D struct declaration. - ) - - $(P D does not support bit fields. If needed, they can be emulated - with shift and mask operations. - $(DPLLINK htod.html, htod) will convert bit fields to inline functions that - do the right shift and masks. - ) - -Object Construction and Destruction
- - $(P Similarly to storage allocation and deallocation, objects - constructed in D code should be destructed in D, - and objects constructed - in C++ should be destructed in C++ code. - ) - -Special Member Functions
- - $(P D cannot call C++ special member functions, and vice versa. - These include constructors, destructors, conversion operators, - operator overloading, and allocators. - ) - -Runtime Type Identification
- - $(P D runtime type identification - uses completely different techniques than C++. - The two are incompatible.) - -C++ Class Objects by Value
- - $(P D can access POD (Plain Old Data) C++ structs, and it can - access C++ class virtual functions by reference. - It cannot access C++ classes by value. - ) - -C++ Templates
- - $(P D templates have little in common with C++ templates, - and it is very unlikely that any sort of reasonable method - could be found to express C++ templates in a link-compatible - way with D. - ) - - $(P This means that the C++ STL, and C++ Boost, likely will - never be accessible from D. - ) - -Exception Handling
- - $(P D and C++ exception handling are completely different. - Throwing exceptions across the boundaries between D - and C++ code will likely not work. - ) - -Future Developments
- - $(P How the upcoming C++0x standard will affect this is not - known.) - - $(P Over time, more aspects of the C++ ABI may be accessible - directly from D.) - -) - -Macros: - TITLE=Interfacing to C++ - WIKI=InterfaceToCPP - - - CATEGORY_SPEC=$0 diff --git a/cppdbc.dd b/cppdbc.dd deleted file mode 100644 index e1d1d81aea..0000000000 --- a/cppdbc.dd +++ /dev/null @@ -1,503 +0,0 @@ -Ddoc - -$(COMMUNITY 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: - - $(OL - - $(LI The $(I assert) is the basic contract. - ) - - $(LI When an assert contract fails, it throws an exception. - Such exceptions can be caught and handled, or allowed to - terminate the program. - ) - - $(LI Classes can have $(I 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. - ) - - $(LI Assert contracts on object references check the class - invariant for that object. - ) - - $(LI Class invariants are inherited, that means that a derived - class invariant will implicitly call the base class invariant. - ) - - $(LI Functions can have $(I preconditions) and $(I postconditions). - ) - - $(LI 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. - ) - - $(LI By throwing a compiler switch, DbC code can be enabled - or can be withdrawn from the compiled code. - ) - - $(LI Code works semantically the same with or without DbC - checking enabled. - ) - - ) - -Contract Programming in C++
- -The $(D assert) Macro
- - C++ does have the basic $(D assert) macro, which tests its argument - and if it fails, aborts the program. $(D assert) can be turned - on and off with the $(D NDEBUG) macro. -- - $(D 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. $(D assert) relies on - a macro text preprocessor to work. -
- - $(D assert) is where explicit support for DbC in Standard C++ - begins and ends. - -
Class Invariants
- - Consider a class invariant in D: - ----------- -class A -{ - $(B invariant)() { ...contracts... } - - this() { ... } // constructor - ~this() { ... } // destructor - - void foo() { ... } // public member function -} - -class B : A -{ - $(B invariant)() { ...contracts... } - ... -} ----------- - - To accomplish the equivalent in C++ (thanks to Bob Bell for providing - this): - -$(CCODE -templatePreconditions 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: - -$(CCODE -void foo() -{ - struct Sentry - { Sentry() { ...preconditions... } - ~Sentry() { ...postconditions... } - } sentry; - ...implementation... -} -) - - If the preconditions and postconditions consist of nothing - more than $(D assert) macros, the whole doesn't need to - be wrapped in a $(D #ifdef) pair, since a good C++ compiler will - optimize the whole thing away if the $(D assert)s are turned off. -- - But suppose $(D 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 $(D #ifdef): - -$(CCODE -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 $(D #ifdef), by - putting the conditions into a template function referenced - by the $(D assert).) -
- - Let's add a return value to $(D 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++: - -$(CCODE -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 $(D foo()). In D: - ----------- -int foo(int a, int b) - in { ...preconditions... } - out (result) { ...postconditions... } - body - { - ...implementation... - if (...) - return bar(); - return 3; - } ----------- - - In C++: - -$(CCODE -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 $(D B.foo()) are: - - $(UL - $(LI Either Apreconditions or Bpreconditions must be satisfied.) - $(LI Both Apostconditions and Bpostconditions must be satisfied.) - ) - - Let's get this to work in C++: - -$(CCODE -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 $(D 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 $(D foo()), - and parameters - for $(D foo()). - -Conclusion
- - These C++ techniques can work up to a point. But, aside from - $(D 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
-
- -) - -Macros: - TITLE=D's Contract Programming vs C++'s - WIKI=CppDbc - - - CATEGORY_OVERVIEW=$0 diff --git a/cppstrings.dd b/cppstrings.dd deleted file mode 100644 index 17b1aae2e2..0000000000 --- a/cppstrings.dd +++ /dev/null @@ -1,583 +0,0 @@ -Ddoc - -$(COMMUNITY 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
- -$(P 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. -) -$(P Additionally, if one has an array of floats, is $(SINGLEQUOTE +) overloaded to - be the same as a vector addition, or an array concatenation? -) -$(P 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
- -$(P 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: -) - -$(CCODE -const char abc[5] = "world"; -string str = "hello" + abc; -) - -$(P That isn't going to work. But it does work when the core language - knows about strings: -) - -$(CCODE -const char[5] abc = "world"; -char[] str = "hello" ~ abc; -) - -Consistency With C String Syntax
- -$(P - There are three ways to find the length of a string in C++: -) - -$(CCODE -const char abc[] = "world"; : sizeof(abc)/sizeof(abc[0])-1 - : strlen(abc) -string str; : str.length() -) - -$(P - 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
- -$(P - C++ strings use a function to determine if a string is empty: -) - -$(CCODE -string str; -if (str.empty()) - // string is empty -) - -$(P - In D, an empty string has zero length: -) - ------------------------ -char[] str; -if (!str.length) - // string is empty ------------------------ - - -Resizing Existing String
- -$(P - C++ handles this with the resize() member function: -) - -$(CCODE -string str; -str.resize(newsize); -) - -$(P - D takes advantage of knowing that str is an array, and - so resizing it is just changing the length property: -) - ------------------------ -char[] str; -str.length = newsize; ------------------------ - -Slicing a String
- -$(P - C++ slices an existing string using a special constructor: -) - -$(CCODE -string s1 = "hello world"; -string s2(s1, 6, 5); // s2 is "world" -) - -$(P - D has the array slice syntax, not possible with C++: -) - ------------------------ -string s1 = "hello world"; -string s2 = s1[6 .. 11]; // s2 is "world" ------------------------ - -$(P - Slicing, of course, works with any array in D, not just strings. -) - -Copying a String
- -$(P - C++ copies strings with the replace function: -) - -$(CCODE -string s1 = "hello world"; -string s2 = "goodbye "; -s2.replace(8, 5, s1, 6, 5); // s2 is "goodbye world" -) - -$(P - D uses the slice syntax as an lvalue: -) - ------------------------ -char[] s1 = "hello world".dup; -char[] s2 = "goodbye ".dup; -s2[8..13] = s1[6..11]; // s2 is "goodbye world" ------------------------ - - $(P The $(CODE .dup) is needed because string literals are - read-only in D, the $(CODE .dup) will create a copy - that is writable. - ) - - -Conversions to C Strings
- -$(P - This is needed for compatibility with C API's. In C++, this - uses the c_str() member function: -) - -$(CCODE -void foo(const char *); -string s1; -foo(s1.c_str()); -) - -$(P - In D, strings can be converted to char* using the .ptr property: -) - ------------------------ -void foo(char*); -char[] s1; -foo(s1.ptr); ------------------------ - $(P although for this to work where $(D foo) expects a 0 terminated - string, $(D s1) must have a terminating 0. Alternatively, the - function $(D std.string.toStringz) will ensure it:) - ------------------------ -void foo(char*); -char[] s1; -foo(std.string.$(B toStringz)(s1)); ------------------------ - - -Array Bounds Checking
- -$(P - 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
- -$(P - 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": - ... -} ------------------------ - -$(P - 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
- -$(P - In C++, this is done with the replace() member function: -) - -$(CCODE -string str = "hello"; -str.replace(1,2,2,'?'); // str is "h??lo" -) - -$(P - In D, use the array slicing syntax in the natural manner: -) - ------------------------ -char[5] str = "hello"; -str[1..3] = '?'; // str is "h??lo" ------------------------ - -Value vs Reference
- -$(P - 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 $(SINGLEQUOTE 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. -) - -$(P - 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 $(SINGLEQUOTE owner) - of the string data. -) - -$(P - 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. -) - -$(P - 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
- -$(P - 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 std.file; -import std.stdio; - -int main (char[][] args) -{ - int w_total; - int l_total; - int c_total; - int[char[]] dictionary; - - writefln(" lines words bytes file"); - for (int i = 1; i < args.length; ++i) - { - char[] input; - int w_cnt, l_cnt, c_cnt; - int inword; - int wstart; - - input = cast(char[])std.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]++; - } - writefln("%8s%8s%8s %s", l_cnt, w_cnt, c_cnt, args[i]); - l_total += l_cnt; - w_total += w_cnt; - c_total += c_cnt; - } - - if (args.length > 2) - { - writefln("--------------------------------------%8s%8s%8s total", - l_total, w_total, c_total); - } - - writefln("--------------------------------------"); - - foreach (char[] word1; dictionary.keys.sort) - { - writefln("%3d %s", dictionary[word1], word1); - } - return 0; -} ------------------------ - - $(P (An $(LINK2 wc.html, alternate implementation) that - uses buffered file I/O to handle larger files.)) - - $(P - Two people have written C++ implementations using the C++ standard - template library, - wccpp1 - and - $(LINK2 #wccpp2, wccpp2). - The input file - $(LINK2 http://www.gutenberg.org/files/11/old/alice30.txt, 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. - ) - - $(TABLE1 - $(TR - $(TH Program) - $(TH Compile) - $(TH Compile Time) - $(TH Run) - $(TH Run Time) - ) - $(TR - $(TD D wc) - $(TD dmd wc -O -release) - $(TD 0.0719) - $(TD wc alice30.txt >log) - $(TD 0.0326) - ) - $(TR - $(TD C++ wccpp1) - $(TD dmc wccpp1 -o -I\dm\stlport\stlport) - $(TD 2.1917) - $(TD wccpp1 alice30.txt >log) - $(TD 0.0944) - ) - $(TR - $(TD C++ wccpp2) - $(TD dmc wccpp2 -o -I\dm\stlport\stlport) - $(TD 2.0463) - $(TD wccpp2 alice30.txt >log) - $(TD 0.1012) - ) - ) - - $(P - The following tests were run on linux, again comparing a D compiler ($(B gdc)) - and a C++ compiler ($(B 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 ($(B dmd)) - is included for comparison. - ) - - - $(TABLE1 - $(TR - $(TH Program) - $(TH Compile) - $(TH Compile Time) - $(TH Run) - $(TH Run Time) - ) - $(TR - $(TD D wc) - $(TD gdc -O2 -frelease -o wc wc.d) - $(TD 0.326) - $(TD wc alice30.txt > /dev/null) - $(TD 0.041) - ) - $(TR - $(TD D wc) - $(TD dmd wc -O -release) - $(TD 0.235) - $(TD wc alice30.txt > /dev/null) - $(TD 0.041) - ) - $(TR - $(TD C++ wccpp1) - $(TD g++ -O2 -o wccpp1 wccpp1.cc) - $(TD 2.874) - $(TD wccpp1 alice30.txt > /dev/null) - $(TD 0.086) - ) - $(TR - $(TD C++ wccpp2) - $(TD g++ -O2 -o wccpp2 wccpp2.cc) - $(TD 2.886) - $(TD wccpp2 alice30.txt > /dev/null) - $(TD 0.095) - ) - ) - - $(P - 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.) - ) - - $(TABLE1 - $(TR - $(TH Program) - $(TH Compile) - $(TH Compile Time) - $(TH Run) - $(TH Run Time) - ) - $(TR - $(TD D wc) - $(TD gdc -O2 -frelease -o wc wc.d) - $(TD 0.28) - $(TD wc alice30.txt > /dev/null) - $(TD 0.03) - ) - $(TR - $(TD C++ wccpp1) - $(TD g++ -O2 -o wccpp1 wccpp1.cc) - $(TD 1.90) - $(TD wccpp1 alice30.txt > /dev/null) - $(TD 0.07) - ) - $(TR - $(TD C++ wccpp2) - $(TD g++ -O2 -o wccpp2 wccpp2.cc) - $(TD 1.88) - $(TD wccpp2 alice30.txt > /dev/null) - $(TD 0.08) - ) - ) --
wccpp2 by Allan Odgaard
- -$(CCODE -#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; -} -) - -) - -Macros: - TITLE=D Strings vs C++ Strings - WIKI=CPPstrings - CATEGORY_OVERVIEW=$0 diff --git a/cpptod.dd b/cpptod.dd deleted file mode 100644 index 0bafe9fed0..0000000000 --- a/cpptod.dd +++ /dev/null @@ -1,818 +0,0 @@ -Ddoc - -$(COMMUNITY Programming in D for C++ Programmers, - - - -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 - -$(UL - $(LI $(LINK2 #constructors, Defining Constructors)) - $(LI $(LINK2 #baseclass, Base class initialization)) - $(LI $(LINK2 #structcmp, Comparing structs)) - $(LI $(LINK2 #typedefs, Creating a new typedef'd type)) - $(LI $(LINK2 #friends, Friends)) - $(LI $(LINK2 #operatoroverloading, Operator overloading)) - $(LI $(LINK2 #usingdeclaration, Namespace using declarations)) - $(LI $(LINK2 #raii, RAII (Resource Acquisition Is Initialization))) - $(LI $(LINK2 #properties, Properties)) - $(LI $(LINK2 #recursivetemplates, Recursive Templates)) - $(LI $(LINK2 #metatemplates, Meta Templates)) - $(LI $(LINK2 #typetraits, Type Traits)) -) - - -
- -
Defining constructors
- -The C++ Way
- - Constructors have the same name as the class: - -$(CPPCODE -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. - -$(CPPCODE -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: - -$(CPPCODE -struct A x, y; -... -x = y; -) - - it does not for struct comparisons. Hence, to compare two struct - instances for equality: - -$(CPPCODE -#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 $(SINGLEQUOTE 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. - -$(CPPCODE -#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. - -$(CPPCODE -#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 $(D friend) declarations: - -$(CPPCODE -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 $(D 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: - -$(CPPCODE -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 $(D 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 $(I using-declaration) in C++ is used to bring a name from - a namespace scope into the current scope: - -$(CPPCODE -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: - -$(CPPCODE -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 $(D synchronized) - declarations and statements. -- - The few RAII issues left are handled by $(I scope) classes. - Scope classes get their destructors run when they go out of scope. - ------- -scope class File -{ Handle h; - - ~this() - { - h.release(); - } -} - -void test() -{ - if (...) - { scope 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: - -$(CPPCODE -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 - $(SINGLEQUOTE 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: - -$(CPPCODE -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() -{ - writefln("%d", factorial!(4)); // prints 24 -} ------- - -- -
Meta Templates
- - The problem: create a typedef for a signed integral type that is at - least $(I 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. - -$(CPPCODE -#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 C++ Boost Way
- - This version uses the C++ Boost library. It was provided - by David Abrahams. - -$(CPPCODE -#include <boost/mpl/if.hpp> -#include <boost/mpl/assert.hpp> - -template <int nbits> struct Integer - : mpl::if_c<(nbits <= 8), signed char - , mpl::if_c<(nbits <= 16), short - , mpl::if_c<(nbits <= 32), long - , long long>::type >::type > -{ - BOOST_MPL_ASSERT_RELATION(nbits, <=, 64); -} - -#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. - ------- -import std.stdio; - -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 ; - writefln("%d %d %d %d", - 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: - -$(CPPCODE -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) principle. - Why it works is a fairly advanced template topic. - -The D Way
- - $(ACRONYM SFINAE, Substitution Failure Is Not An Error) - can be done in D without resorting to template argument - pattern matching: - ------- -template IsFunctionT(T) -{ - static if ( is(T[]) ) - const int IsFunctionT = 0; - else - const int IsFunctionT = 1; -} - -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 $(ISEXPRESSION) expression can test it directly: - ------- -void test() -{ - alias int fp(int); - - assert( is(fp == function) ); -} ------- - - -) - -Macros: - TITLE=Programming in D for C++ Programmers - WIKI=CPPtoD - CATEGORY_OVERVIEW=$0 diff --git a/css/codemirror.css b/css/codemirror.css new file mode 100644 index 0000000000..1067b3ee6b --- /dev/null +++ b/css/codemirror.css @@ -0,0 +1,334 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; + color: black; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; + white-space: nowrap; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; + white-space: nowrap; +} + +.CodeMirror-guttermarker { color: black; } +.CodeMirror-guttermarker-subtle { color: #999; } + +/* CURSOR */ + +.CodeMirror-cursor { + border-left: 1px solid black; + border-right: none; + width: 0; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.cm-fat-cursor .CodeMirror-cursor { + width: auto; + border: 0; + background: #7e7; +} +.cm-fat-cursor div.CodeMirror-cursors { + z-index: 1; +} + +.cm-animate-fat-cursor { + width: auto; + border: 0; + -webkit-animation: blink 1.06s steps(1) infinite; + -moz-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; + background-color: #7e7; +} +@-moz-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@-webkit-keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} +@keyframes blink { + 0% {} + 50% { background-color: transparent; } + 100% {} +} + +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror-overwrite .CodeMirror-cursor {} + +.cm-tab { display: inline-block; text-decoration: inherit; } + +.CodeMirror-ruler { + border-left: 1px solid #ccc; + position: absolute; +} + +/* DEFAULT THEME */ + +.cm-s-default .cm-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-negative {color: #d44;} +.cm-positive {color: #292;} +.cm-header, .cm-strong {font-weight: bold;} +.cm-em {font-style: italic;} +.cm-link {text-decoration: underline;} +.cm-strikethrough {text-decoration: line-through;} + +.cm-s-default .cm-keyword {color: #708;} +.cm-s-default .cm-atom {color: #219;} +.cm-s-default .cm-number {color: #164;} +.cm-s-default .cm-def {color: #00f;} +.cm-s-default .cm-variable, +.cm-s-default .cm-punctuation, +.cm-s-default .cm-property, +.cm-s-default .cm-operator {} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-comment {color: #a50;} +.cm-s-default .cm-string {color: #a11;} +.cm-s-default .cm-string-2 {color: #f50;} +.cm-s-default .cm-meta {color: #555;} +.cm-s-default .cm-qualifier {color: #555;} +.cm-s-default .cm-builtin {color: #30a;} +.cm-s-default .cm-bracket {color: #997;} +.cm-s-default .cm-tag {color: #170;} +.cm-s-default .cm-attribute {color: #00c;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.cm-s-default .cm-error {color: #f00;} +.cm-invalidchar {color: #f00;} + +.CodeMirror-composing { border-bottom: 2px solid; } + +/* Default styles for common addons */ + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} +.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } +.CodeMirror-activeline-background {background: #e8f2ff;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + position: relative; + overflow: hidden; + background: white; +} + +.CodeMirror-scroll { + overflow: scroll !important; /* Things will break if this is overridden */ + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; + border-right: 30px solid transparent; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actual scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; +} +.CodeMirror-gutter-filler { + left: 0; bottom: 0; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + z-index: 3; +} +.CodeMirror-gutter { + white-space: normal; + height: 100%; + display: inline-block; + margin-bottom: -30px; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-wrapper { + position: absolute; + z-index: 4; + background: none !important; + border: none !important; +} +.CodeMirror-gutter-background { + position: absolute; + top: 0; bottom: 0; + z-index: 4; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} +.CodeMirror-gutter-wrapper { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.CodeMirror-lines { + cursor: text; + min-height: 1px; /* prevents collapsing before first draw */ +} +.CodeMirror pre { + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; + -webkit-tap-highlight-color: transparent; +} +.CodeMirror-wrap pre { + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; +} + +.CodeMirror-linebackground { + position: absolute; + left: 0; right: 0; top: 0; bottom: 0; + z-index: 0; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-widget {} + +.CodeMirror-code { + outline: none; +} + +/* Force content-box sizing for the elements where we expect it */ +.CodeMirror-scroll, +.CodeMirror-sizer, +.CodeMirror-gutter, +.CodeMirror-gutters, +.CodeMirror-linenumber { + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; +} + +.CodeMirror-cursor { position: absolute; } +.CodeMirror-measure pre { position: static; } + +div.CodeMirror-cursors { + visibility: hidden; + position: relative; + z-index: 3; +} +div.CodeMirror-dragcursors { + visibility: visible; +} + +.CodeMirror-focused div.CodeMirror-cursors { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } +.CodeMirror-crosshair { cursor: crosshair; } +.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +/* Used to force a border model for a node */ +.cm-force-border { padding-right: .1px; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } +} + +/* See issue #2901 */ +.cm-tab-wrap-hack:after { content: ''; } + +/* Help users use markselection to safely style text background */ +span.CodeMirror-selectedtext { background: none; } diff --git a/css/ddox.css b/css/ddox.css new file mode 100644 index 0000000000..4295bada76 --- /dev/null +++ b/css/ddox.css @@ -0,0 +1,104 @@ +h1 code { font-size: 1em; } +h1 code a { color: inherit; } + +#copyright p { + display: inline; +} + +pre a { text-decoration: none; } +pre a:hover { text-decoration: underline; } + +h1 code a { + text-decoration: none; + color: inherit; + border-bottom: 1px dashed #CCC; +} + +.hyphenate code { + hyphens: manual; +} + +col.caption { + min-width: 170pt; +} + +#navigation #cssmenu a.package { + background-image: none; +} + +span.tableEntryAnnotation { color: #866;} + +a.protected { + font-style: italic; + background-image: url(https://github.com/images/ddox/protected.png); + background-repeat: no-repeat; + background-position: 0pt 2pt; + padding-left: 16px; +} +a.package { + font-style: italic; + background-image: url(https://github.com/images/ddox/package.png); + background-repeat: no-repeat; + padding-left: 16px; +} +a.private { + font-style: italic; + background-image: url(https://github.com/images/ddox/private.png); + background-repeat: no-repeat; + padding-left: 16px; +} +a.inherited:after { content: url(https://github.com/images/ddox/inherited.png); padding-left: 3pt; vertical-align: bottom; } + +#symbolSearchPane label { color: #ddd; } + +#symbolSearch { width: 112pt; } + +#symbolSearchResults { + background: #F5F5F5; + border: 1px solid #CCC; + font-size: small; + list-style: none; + margin: 0; + margin-top: 5px; + padding: 0.3em; + position: absolute; + right: -1px; + top: 100%; + width: 100%; + z-index: 1000; +} + +#symbolSearchResults li { + background-repeat: no-repeat; + background-position: left center; + padding-left: 18px; +} + +#top #symbolSearchResults li a { + color: #B03931; + height: auto; + padding: 0; +} +#symbolSearchResults li a:hover +{ + background: transparent; + color: #742620; + text-decoration: underline; +} + +#symbolSearchResults .deprecated a { color: gray; } +#symbolSearchResults .module { background-image: url(https://github.com/images/ddox/module.png); } +#symbolSearchResults .functiondeclaration { background-image: url(https://github.com/images/ddox/function.png); } +#symbolSearchResults .classdeclaration { background-image: url(https://github.com/images/ddox/class.png); } +#symbolSearchResults .interfacedeclaration { background-image: url(https://github.com/images/ddox/interface.png); } +#symbolSearchResults .structdeclaration { background-image: url(https://github.com/images/ddox/struct.png); } +#symbolSearchResults .variabledeclaration { background-image: url(https://github.com/images/ddox/variable.png); } +#symbolSearchResults .property { background-image: url(https://github.com/images/ddox/property.png); } +#symbolSearchResults .enumdeclaration { background-image: url(https://github.com/images/ddox/enum.png); } +#symbolSearchResults .enummemberdeclaration { background-image: url(https://github.com/images/ddox/enummember.png); } +#symbolSearchResults .aliasdeclaration { background-image: url(https://github.com/images/ddox/alias.png); } +#symbolSearchResults .templatedeclaration { background-image: url(https://github.com/images/ddox/template.png); } + +/* Don't show simple handcrafted cheat sheets. DDOX does a good job generating + * them. */ +table.simple-cheatsheet { display: none; } diff --git a/css/html-skeleton.css b/css/html-skeleton.css new file mode 100644 index 0000000000..41497e65c3 --- /dev/null +++ b/css/html-skeleton.css @@ -0,0 +1,242 @@ +/* + +This file contains one entry for each element defined by html.ddoc. It +is otherwise content-free. Use it as a starting point in defining +display styles based upon html.ddoc. + +*/ + +/* DIV: Formats the "Authors" section */ +.Authors +{ +} + +/* DIV: Formats the "Bugs" section */ +.Bugs +{ +} + +/* DIV: class members (classes, funs, enums etc) */ +.class_members +{ +} + +/* DIV: Formats the "Copyright" section */ +.Copyright +{ +} + +/* DIV: code section introduced with --- and --- */ +.d_code +{ + font-family: "Courier New", monospace; + white-space: pre; +} + +/* SPAN: D comment in code */ +.d_comment +{ +} + +/* SPAN: Declaration, i.e. name introduced with return and parameters +*/ +.d_decl +{ +} + +/* DIV: Description of a declaration */ +.d_decl_dd +{ +} + +/* DIV DIV: Description of an entity defined in the doc */ +.d_decl_dd .sections +{ +} + +/* DIV DIV DIV: Summary of an entity defined in the doc */ +.d_decl_dd .sections .summary +{ +} + +/* SPAN: D keyword in code */ +.d_keyword +{ +} + +/* SPAN: D keyword in code */ +.d_keyword +{ +} + +/* SPAN: parameter style inside function description. Warning, +parameters will be rendered in this style everywhere.*/ +.d_param +{ +} + +/* SPAN: Symbol being introduced */ +.d_psymbol +{ +} + +/* SPAN: D string in code */ +.d_string +{ +} + +/* SPAN: D module title */ +.d_title +{ +} + +/* SPAN: link to Phobos resource */ +.phobos_src +{ +} + +/* DIV: Formats the "Date" section */ +.Date +{ +} + +/* SPAN: Highlight of D keywords? */ +.ddoc_keyword +{ +} + +/* DIV: Formats the "Deprecated" section */ +.Deprecated +{ +} + +/* DIV: Formats the description of an item */ +.description +{ +} + +/* DIV: Formats the description of enum members */ +.enum_members +{ +} + +/* DIV: Formats the "Examples" section */ +.Examples +{ +} + +/* SPAN: This is one of those "Authors:" thingies */ +.explanation_item +{ +} + +/* DIV: This is one of those "Authors: xyz" thingies */ +.explanatory +{ +} + +/* DIV: Formats the "History:" section */ +.History +{ +} + +/* DIV: Formats the "License:" section */ +.License +{ +} + +/* DIV: default style of members (inside classes, structs, enums, +templates) */ +.members +{ +} + +/* DIV: Top-level module members (classes, funs, enums etc) */ +.module_members +{ +} + +/* SPAN: Formats a parameter name all over the description. */ +.param +{ +} + +/* SPAN: Formats a parameter description */ +.param_desc +{ +} + +/* SPAN: Formats a parameter name */ +.param_id +{ +} + +/* TABLE: Formats the parameters table */ +.parameters +{ +} + +/* DIV: Formats the "Params:" section */ +.Params +{ +} + +/* SPAN: Name introduced by a declaration */ +.psymbol +{ +} + +/* DIV: Formats the "Returns:" section */ +.Returns +{ +} + +/* DIV: Formats the "See_Also:" section */ +.See_Also +{ +} + +/* SPAN: Formats a section with an undefined name */ +.section +{ +} + +/* SPAN: Formats the header of a section with an undefined name */ +.section_h +{ +} + +/* DIV: Sections of the document, pretty much the entire doc */ +.sections +{ +} + +/* DIV: Members of a struct */ +.struct_members +{ +} + +/* DIV: Formats the "Standards:" section */ +.Standards +{ +} + +/* DIV: Summary of the module or of a documented entity */ +.summary +{ +} + +/* DIV: Formats the description of a template's members */ +.template_members +{ +} + +/* DIV: Formats the "Throws:" section */ +.Throws +{ +} + +/* DIV: Formats the "Version:" section */ +.Version +{ +} diff --git a/css/print.css b/css/print.css index 19d7371980..72a3575f4c 100644 --- a/css/print.css +++ b/css/print.css @@ -8,9 +8,19 @@ pre { overflow: visible; overflow-X: hidden; + font-size: 100%; } -#search-box, #header, #navigation, #lastupdate, #tools, #google_ad, #footernav, #copyright +#search-box, +#header, +#navigation, +#lastupdate, +#tools, +#footernav, +#copyright, +#github-ribbon, +#top, +.page-contents { display: none; } @@ -22,5 +32,5 @@ div#content margin: 0; padding: 0; font-family: serif; - font-size: 12pt; + font-size: 10pt; } diff --git a/css/style.css b/css/style.css index c6fbedc407..6d7796b688 100644 --- a/css/style.css +++ b/css/style.css @@ -1,643 +1,2235 @@ +/* + +-- Colors -- + +Greys: + +white +#FCFCFC +#F5F5F5 +#E6E6E6 +#CCC +#ADADAD +#999 +#555 +#333 - main text + +Reds: + +#B03931 - our main red +#742620 - focus/hover + +#D8645E - on dark background +#F47069 - focus/hover on dark background + +#98312A +#943029 + +-- Font Sizes -- + +Keep the number of different font sizes low. The different heading levels +(h1, ... h6) get specific sizes. Other than that, try to use 'small' and +'large'. + +-- Misc -- + +border-radius: always 4px + +*/ + +@import url(https://fonts.googleapis.com/css?family=Roboto+Slab:300,400,700); + +body, .d_decl .quickindex +{ + font-family: "Roboto Slab", sans-serif; +} + +pre, code, .tt, .d_inlinecode, td.param_id, .CodeMirror pre, .d_decl +{ + font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace; +} +pre, .CodeMirror pre +{ + font-size: small; +} + +pre div.blankline { display: none; } +ol div.blankline { display: none; } +ul div.blankline { display: none; } + body { - padding: 0; - border: 0; - color: black; - background-color: #1f252b; - background-image: url(https://github.com/images/gradient-red.jpg); - background-repeat: no-repeat; - font-size: 100%; - font-family: Verdana, "Deja Vu", "Bitstream Vera Sans", sans-serif; - min-width: 60em; -/* max-width: 1590px; */ - margin: 0px auto; + background: white; + color: #333; + font-size: 93.75%; + line-height: 1.4; + margin: 0; + padding: 0; +} + +#top > .helper, +body > .container, +body#Home #content #tools > div, +body#Home #content > .intro > div, +body#Home #content > .more +{ + margin: auto; + max-width: 76em; + padding: 0 1em; +} + +body > .container +{ + position: relative; +} + +body.doc input, +body.doc textarea, +body.std input, +body.std textarea +{ + background: white; + color: #333; +} + +/* top nav bar */ + +#top +{ + background: #B03931; + border-bottom: 1px #98312A solid; + position: relative; +} + +#top > .helper > .helper +{ + display: table; + width: 100%; +} + +#top #cssmenu, +#top .search-container +{ + display: table-cell; + vertical-align: middle; +} + +#top .search-container +{ + width: 0; /* shrink to content size */ +} + +#top .logo +{ + display: block; + float: left; + margin-left: -5.4em; + margin-right: -4em; + padding-top: 1px; +} + +#top img#logo +{ + height: 2.533em; + vertical-align: middle; + width: 13.69em; +} + +#top #d-language +{ + display: none; +} + +#top a.hamburger +{ + display: none; +} + +#top a +{ + color: white; + text-decoration: none; +} + +#top a:hover, +#top #cssmenu li.open > a, +#top #cssmenu li.active > a +{ + background: #98312A; +} + +#top .expand-container +{ + position: relative; +} + +/* main menu */ + +#top #cssmenu +{ + width: 100%; /* take all available space */ +} + +/* Hide expandable sections by default in #cssmenu. They have fallback URLs. */ +#top #cssmenu .expand-container > * +{ + display: none; +} +#top #cssmenu .expand-container.open > *, +#top #cssmenu .expand-container > .expand-toggle +{ + display: block; +} + +#top #cssmenu ul +{ + list-style: none; + margin: 0; + padding: 0; +} + +#top #cssmenu a, #top .search-container a +{ + display: block; + height: 1.4em; /* Not sure why, but without this the expandable items would + get half a pixel taller than the others. */ + padding: 0.6em 1em; + position: relative; + white-space: nowrap; +} + +#top #cssmenu > ul > li +{ + float: left; +} + +#top #cssmenu > ul > li > ul +{ + background: #B03931; + border: 1px solid #98312A; + + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + + -moz-box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + -webkit-box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + + position: absolute; + z-index: 5; +} + +#top #cssmenu > ul > li > ul > li > a +{ + font-size: small; + padding-top: 0.3em; + padding-bottom: 0.3em; + padding-right: 2em; +} + +#top #cssmenu > ul > li > ul > li:first-child > a +{ + padding-top: 0.6em; +} + +#top #cssmenu > ul > li > ul > li:last-child > a +{ + padding-bottom: 0.6em; +} + + +#top #cssmenu > ul > li .menu-divider +{ + border-top: 1px solid #943029; +} + +#top #cssmenu > ul > li .menu-divider:before +{ + border-top: 1px solid rgba(255, 255, 255, 0.1); + display: block; + height: 1px; + content: ''; +} + +/* search box */ + +#top .search-container.expand-container .expand-toggle +{ + display: none; +} +#top .search-container.expand-container .expand-toggle::after +{ + content: "\f002 \f0d7"; /* f002 = search; f0d7 = caret down */ + font-family: FontAwesome; +} + +#top .search-container.expand-container .expand-toggle span +{ + display: none; +} + +#top #search-box +{ + display: block; /* Don't hide even though it's in a .expand-container. */ + padding-left: 1em; +} + +div#search-box form, span#search-query, span#search-dropdown, span#search-submit +{ + border: 1px none #CCC; +} + +div#search-box form +{ + background: white; + + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + + border-style: solid; + display: inline-block; + font-size: small; + margin: 0; + vertical-align: middle; + white-space: nowrap; +} + +span#search-query, +span#search-dropdown, span#search-dropdown > .helper, +span#search-submit +{ + display: inline-block; + height: 2em; + line-height: 1.3; + vertical-align: top; +} + +span#search-query +{ + width: 8em; +} + +span#search-query input, span#search-dropdown select, span#search-submit button +{ + background: transparent; + color: #333; + border: none; + font-size: small; + margin: 0; + padding: 0 0.5em; + width: 100%; + height: 100%; + outline: none; +} + +span#search-dropdown > .helper +{ + display: inline-block; + position: relative; + overflow: hidden; + width: 8em; +} + +span#search-dropdown > .helper::after +{ + content: "\f0d7"; /* caret down */ + font-family: FontAwesome; + position: absolute; + width: 1em; + line-height: 1em; + top: 0.5em; + right: 0.2em; +} + +span#search-dropdown select +{ + padding-right: 7.5em; + position: relative; + text-overflow: ellipsis; + width: 14em; /* Pushing the native dropdown arrow into invisibility. */ + z-index: 1; + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +span#search-dropdown select::-ms-expand /* IE */ +{ + display: none; +} + +span#search-submit +{ + background: #E6E6E6; + border-left-style: solid; + line-height: 1.2em; + width: 3em; +} + +span#search-submit button +{ + color: #555; +} + +span#search-submit button:active +{ + position: relative; + top: 0.1em; +} + +span#search-submit span /* hide 'go' */ +{ + display: none; +} + +/* subnav */ + +.subnav, .subnav-helper +{ + background: #F5F5F5; + border: 0 solid #CCC; + border-width: 0 1px 1px; + padding-left: 1em; + padding-right: 1em; + width: 15em; +} + +.subnav +{ + float: left; + padding-bottom: 2em; + position: relative; +} + +.subnav a +{ + text-decoration: none; +} + +.subnav a:hover, .subnav .expand-toggle:hover +{ + text-decoration: underline; +} + +.subnav .smallprint a +{ + text-decoration: underline; +} + +.subnav h2 +{ + border-bottom: 1px solid #CCC; + font-size: 1em; + margin-right: -1em; +} + +/* Hide JS toggle. It's only displayed in the narrow layouts. */ +body.have-javascript .subnav.expand-container > h2.expand-toggle +{ + display: none; +} + +/* Hide links that just duplicate the subnav contents. They're only displayed +in the narrow layouts without JS. */ +.subnav .subnav-duplicate +{ + display: none; +} + +.subnav ul +{ + list-style: none; + margin: 0; + padding-left: 1em; +} +.subnav > ul +{ + padding-left: 0; +} + +.subnav li a +{ + display: block; + position: relative; + /* white-space: nowrap; */ +} + +.subnav li.active > a +{ + color: #742620; + text-decoration: underline; +} + +.subnav .hide-from-nav +{ + display: none; +} + +/* hierarchy tree lines */ + +body.std .subnav ul ul ul +{ + border-left: 1px solid #CCC; +} + +body.std .subnav .d_inlinecode +{ + display: block; + font-weight: normal; + overflow: hidden; + text-overflow: ellipsis; +} + +body.std .subnav li li > a > span, +body.std .subnav li li > h7 > span +{ + border-left: 1px solid #CCC; +} + +body.std .subnav ul ul li > a > span::before, +body.std .subnav ul ul li > h7 > span::before +{ + border-bottom: 1px solid #CCC; + content: ""; + display: inline-block; + width: 0.5ex; + margin-right: 0.5ex; + + height: 1em; + position: relative; + bottom: 0.5ex; +} + +body.std .subnav ul ul li:last-child > ul +{ + border-left: none; +} + +body.std .subnav ul ul li:last-child > a > span, +body.std .subnav ul ul li:last-child > h7 > span +{ + border-left: none; +} + +body.std .subnav ul ul li:last-child > a > span::before, +body.std .subnav ul ul li:last-child > h7 > span::before +{ + border-left: 1px solid #CCC; +} + +/* Don't show ddox package symbols in the subnav. */ +body.std .subnav a.package +{ + background: none; + padding-left: 0; + font-style: normal; +} + +.subnav-helper +{ + bottom: 0; + content: ""; + position: absolute; + top: 0; +} + +#content +{ + padding-bottom: 1em; + text-align: justify; +} + +/* This is a CSS hack to only target Blink based browsers + Targets Chrome 28 and later and Opera 14 and later +*/ +@media all and (-webkit-min-device-pixel-ratio:0) and (min-resolution: .001dpcm) { + #content + { + /* because Blink based browsers don't support hyphens */ + text-align: left; + } +} + +.subnav + #content +{ + margin-left: 19em; +} + +#content #tools +{ + padding: 0.3em 0 0.6em 0; + text-align: right; +} + +#content #tools .tip +{ + display: inline-block; + padding-left: 0.5em; +} + +.expand-container > .expand-toggle::after +{ + content: " \f0d7"; /* caret down */ + font-family: FontAwesome; +} +body.have-javascript .expand-container.open > .expand-toggle::after +{ + content: " \f0d8"; /* caret up */ +} + +body.have-javascript .expand-container > * +{ + display: none; +} + +/* Not hiding .subnav by default; only in the narrow layouts. */ +body .subnav.expand-container > * +{ + display: block; +} + +body.have-javascript .expand-container.open > *, +body.have-javascript .expand-container > .expand-toggle +{ + display: block; +} + +/* show signature download on hover */ +span.sig_btn +{ + display: inline-block; +} + +span.sig_btn > a:last-child +{ + visibility: hidden; +} + +span.sig_btn:hover > a:last-child +{ + visibility: visible; +} + +a.btn +{ + color: #333; + background: white; + border: 1px solid #CCC; + border-radius: 4px; + padding: 0.3em 0.6em; + display: inline-block; + text-decoration: none; +} + +a.btn:hover +{ + background-color: #E6E6E6; + border-color: #ADADAD; + color: #333; +} + +.btn.donate-large +{ + font-size: 22px; + padding: 0.4em 1em; + background-color: #B03931; + color: white; + border: #B03931; +} +.btn.donate-large:hover +{ + background-color: #98312A; + color: white; +} + +/* only grow as wide as necessary */ +div.btn-group-vertical +{ + display: inline-block; +} + +/* make all elements the same width */ +div.btn-group-vertical > a, +div.btn-group-vertical > span +{ + display: block; +} + +/* distribute multiple elements evenly in a row */ +div.btn-group-vertical > div.hbox +{ + display: flex; +} + +div.btn-group-vertical > div.hbox > a +{ + flex-grow: 1 +} + +/* replaces tag */ +em.big +{ + font-style: normal; + font-size: larger; +} + +/* replaces tag */ +em.tt +{ + font-style: normal; +} + +/* replaces tag */ +em.u +{ + font-style: normal; + text-decoration: underline; +} + +table.params +{ + border: 1px dotted #333; +} + +tr.param +{ + border: none; + border-bottom: 1px dotted gray; +} + +tr:last-child +{ + border-bottom: none; +} + +td.param_id +{ + border: inherit; + font-weight: bold; + padding-right: 1em; + white-space: nowrap; + vertical-align: top; +} + +td.param_desc +{ + border: inherit; + font-style: italic; +} + +.download-tables > .download-compilers { + flex-grow: 1; + flex-shrink: 0; +} + +.download-tables { + display: flex; + gap: 2.5em; + align-items: center; +} + +@media screen and (max-width: 65em) { + .download-tables { + flex-direction: column; + } +} + +table.lsp { + max-width: 30em; + background-color: white; + border: none; + border-radius: 0.5em; + border-top-left-radius: 0.25em; + border-top-right-radius: 0.25em; + /* TODO: currently with shadow, since it's new and shiny, make this fit with the other content eventually */ + box-shadow: 0 1px 2px rgba(0,0,0,0.2), 0 5px 7px rgba(0,0,0,0.2); + position: relative; +} + +table.lsp tbody > tr:nth-child(1) > td:before { + display: block; + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 0.5em; + background-color: #B03931; + border-top-left-radius: 0.25em; + border-top-right-radius: 0.25em; +} + +table.lsp img { + background-color: white; + border-radius: 0.5em; + padding: 0.5em; +} + +table.lsp td { + padding: 1em; +} + +table.lsp tbody > tr:nth-child(1) > td { + padding-bottom: 0; + padding-top: 1.5em; +} + +table.download-compilers +{ + width: 100%; + max-width: 50em; + table-layout: fixed; +} + +.download-tables table td +{ + border: none; +} + +.download-tables h2 +{ + margin: 0; + margin-bottom: 4pt; + text-align: center; +} + +.download-tables table > tbody > tr:first-child > td +{ + text-align: center; + vertical-align: middle; +} + +.download-tables table > tbody > tr:nth-child(2) > td +{ + text-align: left; +} + +.download-tables table > tbody > tr:nth-child(2) > td > ul +{ + margin-bottom: 0; + padding-left: 1em; +} + +.download-tables table div.download-link +{ + text-align: center; + margin-bottom: 1em; +} + +table.download-compilers img +{ + width: 100%; +} + +table.lsp img +{ + width: 100%; + max-width: 8em; + margin: 0; +} + +.download-tables table h3 +{ + margin-top: 0; + text-align: center; +} + +div#download-choose +{ + float: right; +} + +.download_image +{ + display: inline-block; + width: 100px; + vertical-align: top; +} + +h3.download +{ + display: inline-block; +} + +.download_paragraph +{ + display: inline-block; +} + +.download_paragraph > h3 +{ + margin: 0; +} + +/* release | beta | nightly */ +.download_channels +{ + word-spacing: 2em; +} + +.download_channel +{ + display: inline-block; + word-spacing: initial; +} + +.footnote +{ + font-style: italic; +} +.footnote::before { content: " ("; } +.footnote::after { content: ")"; } + +.gname +{ + font-style: italic; +} + +.metacode +{ + font-style: italic; +} + +.key +{ + font-weight: bold; + display: block; +} + +.hyphenate +{ + -webkit-hyphens: auto; + -moz-hyphens: auto; + -epub-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; +} + +.donthyphenate +{ + -webkit-hyphens: manual; + -moz-hyphens: manual; + -epub-hyphens: manual; + -ms-hyphens: manual; + hyphens: manual; +} + +.black { color: black; } +.blue { color: blue; } +.green { color: green; } +.red { color: red; } +.white { color: white; } +.yellow { color: yellow; } + +.bigoh +{ + font-weight: bold; +} + +div.summary, div.description, div.keyval, div.blankline +{ + margin: 1em 0; } h1, h2, h3, h4, h5, h6 { - font-family: Georgia, "Times New Roman", Times, serif; - font-weight: normal; - color: #633; - line-height: normal; - text-align: left; + font-weight: normal; + line-height: normal; + text-align: left; + margin: 2em 0 1em; } h1 { - margin-top: 0; - font-size: 2.5em; + font-size: 2.0em; + margin-top: 0; } h2 { - font-size: 1.7em; + font-size: 1.5em; } h3 { - font-size: 1.35em; + font-size: 1.35em; } h4 { - font-size: 1.15em; - font-style: italic; - margin-bottom: 0; + font-size: 1.15em; } +h5 +{ + font-size: 1em; +} +/*This is to support the "Programming in D" book*/ +h6 { + font-size: 1em; + color:#000033; + font-weight:bold; +} +.chapter { + font-size: 2em; + color:#000033; +} +.subsection { + font-size: 1.15em; + color:#000033; + font-weight:bold; +} form { - margin: 0; + margin: 0; } blockquote { - font-family: Georgia, "Times New Roman", Times, serif; - background-color: #e5e5e5; - display: block; - padding: 0.25em 1em; - margin: 1em 2em; + background-color: #e5e5e5; + display: block; + padding: 0.25em 1em; + margin: 1em 2em; } blockquote p:before { - content: "\201C"; - font-family: Georgia, "Times New Roman", Times, serif; - color: #bacaca; - display: block; - font-size: 700%; - width: 50px; - height: 0; - margin-left: -0.5em; - line-height: 0.8em; + content: "\201C"; + color: #bacaca; + display: block; + font-size: 700%; + width: 50px; + height: 0; + margin-left: -0.5em; + line-height: 0.8em; } blockquote p { - margin: 0; - font-style: italic; + margin: 0; + font-style: italic; } blockquote cite { - display: block; - text-align: right; + display: block; + text-align: right; } +/* pre.prettyprint and div.prototype come from prettyprint.js */ +pre, pre.prettyprint, div.prototype +{ + background: white; + border-radius: 4px; + padding: 1ex; + margin: 1em 0 1em 0; + line-height: normal; + border: 1px solid #ccc; + width: auto; +} pre { - background: white; - padding: 1ex; - margin: 1em 0 1em 3em; - font-family: monospace; - font-size: 1.2em; - line-height: normal; - border: 1px solid #ccc; - width: auto; - white-space: pre-wrap; /* css-3 */ - white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ - white-space: -pre-wrap; /* Opera 4-6 */ - white-space: -o-pre-wrap; /* Opera 7 */ - word-wrap: break-word; /* Internet Explorer 5.5+ */ + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ } -dd +dd, .d_decl_dd { - padding: 1ex; - margin-left: 3em; - margin-bottom: 1em; + margin: 0; + margin-bottom: 2em; + padding: 1ex; + padding-left: 2em; } -table, tr, td, th +.template_param_list { - /*border-style: solid;*/ + color: #48688E; } -td +.constraint { - text-align: justify; + opacity: .35; } -hr +.constraint:before { + content: "Constraints: "; + visibility: hidden; +} + +.constraint:hover:before { + visibility: visible; +} + +.constraint:hover { + opacity: 1; +} + +table { - margin: 2em 0; + border: solid #333; + border-width: 2px 0; + border-collapse: collapse; } -a +table tr { - color: #006; + border: none; } -a:visited +table td, table th, table caption { - color: #606; + text-align: left; + vertical-align: top; + padding: 0.3em; } -/* These are different kinds of sections */
-.bnf /* grammar */
+.quickindex .book caption:empty
{
- background-color: white;
- color: #000066;
+ padding: 0px;
}
-.ddoccode
+table td
{
- background-color: #f3eeee;
- color: #000066;
+ border: none;
+ border-bottom: 1px solid #E6E6E6;
}
-.console /* command line console */
+table th
{
- background-color: #f7f7f7;
- color: #181818;
+ border: none;
+ border-bottom: 1px solid #333;
}
-.moddeffile /* module definition file */
+table td:not(:last-child), table th:not(:last-child)
{
- background-color: #efeffe;
- color: #010199;
+ padding-right: 1em;
}
-.scini /* sc.ini configuration file */
+/*
+ These next two rules are for pages like:
+ http://dlang.org/phobos-prerelease/std_regex.html
+
+ The idea is if we have a list of links, we want space
+ to the right of each one. But detecting a list of links
+ vs just a single link requires some thought: the css
+ adjacent sibling rule does well detecting all but the first
+ one in a list, so we'll add space to the right of them (that's
+ the second rule here), but that leaves an inconsistent space
+ after the first item.
+
+ That's where the following rule comes in: on the item directly
+ following the first link, add some left padding to simulate the
+ first one having the same space as the others.
+*/
+table.book tbody a:first-child + a
{
- background-color: #fef6fe;
- color: #111199;
+ padding-left: .6em;
}
-.d_code /* D code */
+table.book tbody a + a
{
- background-color: #fcfcfc;
- color: #000066;
+ padding-right: .6em;
}
-.d_code2 /* D code */
+hr
{
- background-color: #fcfcfc;
- color: #000066;
+ margin: 2em 0;
}
-.asmcode /* Asm code */
+a, .question, .expand-toggle
{
- background-color: #afcbde;
- color: #000066;
+ color: #B03931;
+ cursor: pointer;
}
-.ccode /* C code */
+a:hover, .question:hover, .expand-toggle:hover
{
- background-color: #f6ecf0;
- color: #000066;
+ color: #742620;
}
-.cppcode /* C++ code */
+/*
+Styling for page anchor self-links.
+
+These links look like regular headers unless hovered, in which case
+they are underlined and display a pilcrow after them.
+*/
+a.anchor
{
- background-color: #f6ecf0;
- color: #000066;
+ color: #633; /* Use the regular header text color */
+ text-decoration: none; /* Don't underline unless hovered */
}
-.cppcode2 /* C++ code */
+a.anchor:hover
{
- background-color: #f6ecf0;
- color: #000066;
+ text-decoration: underline; /* See above */
}
-td .d_code2, td .cppcode2, td .cppcode
+a.anchor:hover::after
{
- min-width: 20em;
- margin: 1em 0em;
+ content: " \00B6"; /* Unicode pilcrow symbol */
+ color: #333; /* Pilcrow should not use the regular header text color */
+ font-style: normal; /* ... and should not be italic */
}
-.d_inlinecode
+/* Avoid inserting the pilcrow in the middle of the line on the compiler pages */
+
+body.dcompiler dt a.anchor:hover::after
{
- font-family: monospace;
- /* font-size: 1.2em; */
- font-weight: bold;
+ display: none;
}
-/* Elements of D source code text */
-.d_comment { color: green; }
-.d_string { color: red; }
-.d_keyword { color: blue; }
-.d_psymbol { text-decoration: underline; }
-.d_param { font-style: italic; }
+body.dcompiler dt a.anchor:hover
+{
+ position: relative;
+}
-/* Focal symbol that is being documented */
-.ddoc_psymbol { color: #336600; }
+body.dcompiler dt a.anchor:hover:before
+{
+ content: " \00B6";
+ color: #333;
+ font-style: normal;
+ position: absolute;
+ left: -1em;
+}
-div#top
+/* These are different kinds of sections */
+.bnf /* grammar */
{
-/* max-width: 85em; */
+ background-color: white;
}
-div#header
+.ddoccode
{
- padding: 0.2em 1em 0.2em 1em;
+ background-color: #f3eeee;
}
-img#logo
+.console /* command line console */
+{
+ background-color: #333;
+ border-color: #333;
+ color: #F5F5F5;
+}
+.console a
{
- vertical-align: bottom;
+ color: #D8645E;
+}
+.console a:hover
+{
+ color: #F47069;
}
-/*div#d-language a*/
-#d-language
+.moddeffile /* module definition file */
{
- color: white;
- font-size: 1.7em;
- font-family: Georgia, "Times New Roman", Times, serif;
- font-variant: small-caps;
- text-decoration: none;
+ background-color: #efeffe;
+ color: #010199;
}
-div#search-box
+.scini /* sc.ini configuration file */
{
- background-color: transparent;
- float: right;
- margin-top: 1em;
- margin-right: 1em;
- text-align: right;
+ background-color: #fef6fe;
+ color: #111199;
}
-div#search-box img, div#search-box input, div#search-box select
+.d_code, .d_code2 /* D code */
{
- margin: 0;
- padding: 0;
- vertical-align: middle;
+ background-color: #fcfcfc;
}
-div#search-box input#q
+.asmcode /* Asm code */
{
- border: 0px;
- height: 22px;
- background-image: url(https://github.com/images/search-bg.gif);
- color: black;
+ background-color: #afcbde;
+ border-color: #afcbde;
}
-div#search-box select
+.ccode, .cppcode, .cppcode2 /* C/C++ code */
{
- width: 14em;
+ background-color: #fcfcfc;
}
-div#search-box input#q:focus
+td .d_code2, td .cppcode2, td .cppcode
{
- outline: none;
+ min-width: 20em;
+ margin: 1em 0;
}
+.d_inlinecode
+{
+ font-weight: bold;
+}
-div#navigation
+.d_title
{
- font-size: 0.875em;
- float: left;
- width: 11.5em;
- padding: 0 1.5em;
+ font-weight: bold;
+ text-overflow: clip;
+ overflow: hidden;
+ display: block;
+ word-wrap: break-word;
+ font-family: Consolas, "Bitstream Vera Sans Mono", "Andale Mono", Monaco, "DejaVu Sans Mono", "Lucida Console", monospace;
}
-div#content
+.phobos_src
{
- text-align: justify;
- min-height: 440px;
- margin-left: 13.5em;
- padding: 1.6em;
- padding-top: 1.3em;
- padding-bottom: 1em;
- margin-right: 0.5em;
- border: 0.4em solid #ccd5d5;
- background-color: #f6f6f6;
- font-size: 0.875em;
- line-height: 1.4em;
- text-align: justify;
+ text-overflow: clip;
+ overflow: hidden;
+ display: block;
+ word-wrap: break-word;
}
-body.chm
+/* syntax highlighting
+
+d_* classes come from Ddoc.
+cm-* classes come from CodeMirror.
+
+These classes come from prettify.js:
+.pln - plain text
+.str - string content
+.kwd - keyword
+.com - comment
+.typ - type name
+.lit - literal value
+.pun - punctuation
+.opn - lisp open bracket
+.clo - lisp close bracket
+.tag - markup tag name
+.atn - markup attribute name
+.atv - markup attribute value
+.dec - declaration
+.var - variable name
+.fun - function name
+
+*/
+
+.d_comment,
+.cm-s-eclipse span.cm-comment,
+.com
{
- min-width: 0 !important;
+ color: #999;
}
-body.chm div#content
+.d_string,
+.cm-s-eclipse span.cm-string, .cm-s-eclipse span.cm-string-2,
+.str, .atv
{
- padding: 20px;
- border: none;
- margin: 0 !important;
+ color: #DC4040;
}
-body.chm div#tools
+.d_keyword,
+.cm-s-eclipse span.cm-keyword, .cm-s-eclipse span.cm-builtin,
+.kwd
{
- margin-right: 0;
+ color: #4040DC;
}
-div#twitter
+.typ
{
- color: white;
- font-size: 0.875em;
- float: right;
- width: 16em;
- padding: 1em 1em;
- margin-top: -1em;
+ color: #4040DC;
}
-div.navblock
+
+.d_param
{
- margin-top: 0;
- margin-bottom: 1em;
+ font-style: italic;
}
-div#navigation .navblock h2
+/* .cm-meta is here because it and .lit both match @-attributes */
+.cm-s-eclipse span.cm-number, .cm-s-eclipse span.cm-meta,
+.lit
{
- font-family: Verdana, "Deja Vu", "Bitstream Vera Sans", sans-serif;
- font-size: 1.35em;
- color: #ccc;
- margin: 0;
+ color: #8E00DC;
}
-div#navigation .navblock ul
{
- list-style-type: none;
- margin: 0;
- padding: 0;
+ color: #333;
}
-div#navigation .navblock li
+.cm-s-eclipse span.cm-attribute,
+.atn
{
- margin: 0 0 0 0.8em;
- padding: 0;
+ color: #9ad452;
}
-#navigation .navblock a
+.cm-s-eclipse span.cm-tag,
+.tag
{
- display: block;
- color: #ccc;
- text-decoration: none;
- padding: 0.1em 0;
- border-bottom: 1px dotted #494949;
+ color: #ffaa00;
}
-#navigation .navblock a:hover
+.cm-s-eclipse span.cm-error
{
- color: #eee;
+ color: #f00;
}
-#navigation .navblock a.active
+.cm-s-eclipse span.cm-def, .cm-s-eclipse span.cm-operator,
+.cm-s-eclipse span.cm-property, .cm-s-eclipse span.cm-variable,
+.cm-s-eclipse span.cm-variable-2, .cm-s-eclipse span.cm-variable-3,
+.pln, .fun
+.dec, .var
{
- color: white;
- border-color: white;
+ color: #333;
}
+.cm-s-eclipse span.cm-word {color: #006;}
+.cm-s-eclipse span.cm-atom {color: #219;}
+.cm-s-eclipse span.cm-qualifier {color: #555;}
+.cm-s-eclipse span.cm-bracket {color: #cc7;}
+.cm-s-eclipse span.cm-link {color: #219;}
-div#translate
+
+.ddoc_keyword
{
- margin-top: 3em;
- margin-left: 0;
- color: #ccc;
+ font-weight: bold;
}
+.ddoc_param
+{
+ font-style: italic;
+}
-div#tools
+/* Focal symbol that is being documented */
+.d_psymbol, .ddoc_psymbol
{
- margin: -1.5em;
- margin-bottom: 0;
- text-align: right;
+/* color: #B03931; */
+ font-weight: bold;
}
-div#tools span
+.d_decl
+{
+ background: #F5F5F5;
+ border-left: 5px solid #B03931;
+ text-align: left;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.d_decl > div
{
- padding-left: 0.5em;
- font-size: 0.8em;
- font-style: italic;
- color: #666;
+ border: 1px solid #E6E6E6;
+ border-top-right-radius: 4px;
+ padding: 0.6em 1em;
}
-div#tools a
+.d_decl + dd
{
- color: #666;
+ border: 1px solid #E6E6E6;
+ border-top: none;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
}
-div#tools img
+img
{
- vertical-align: middle;
+ border: 0;
}
+body.chm div#news,
+body.chm div.subnav-helper,
+body.chm div.subnav,
+body.chm div#top
+{
+ display: none;
+}
-div#content li
+body.chm
{
- padding-bottom: .7ex;
+ min-width: 0 !important;
}
+body.chm div#content
+{
+ padding: 20px;
+ border: none;
+ margin: 0 !important;
+ border-radius: 0;
+}
-div#google_ad
+body.chm div#tools
{
- margin-top: 6em;
+ margin-right: 0;
}
+body.chm dt.d_decl
+{
+ width: 100%;
+}
-div#footernav
+.boxes
{
- clear: both;
-/* margin-top: 2em; */
- padding: 1em 2em 0 2em;
-/* background-color: #303333; */
- color: #666;
- text-align: center;
- font-size: 80%;
+ margin: 2em 0;
}
-div#footernav a
+.boxes .row
{
- color: #ccc;
+ display: table-row;
}
-div#footernav a:hover
+.boxes .item
{
- color: white;
+ display: table-cell;
+ width: 50%;
}
+.boxes > .row > .item
+{
+ padding: 1em 2em;
+}
-div#copyright
+.boxes > .row > .item > h4:first-child
{
- padding: 1em 2em;
-/* background-color: #303333; */
- color: #ccc;
- font-size: 50%;
- text-align: center;
+ margin-top: 0;
}
-div#copyright a
+.boxes > .row:first-child > .item
{
- color: #ccc;
+ padding-top: 0;
}
+.boxes > .row:last-child > .item
+{
+ padding-bottom: 0;
+}
-/* These are for the newsgroup archives */
-div#newsnav
+.boxes > .row > .item:first-child
{
- margin-top: -1.5em;
- margin-bottom: -1em;
+ padding-left: 0;
}
-div#Posting
+
+.boxes > .row > .item:last-child
{
- border: 1px solid #cccccc;
- margin-bottom: 1em;
+ padding-right: 0;
}
-div#PostingHeading
+
+.tip
{
- font-family: Georgia, "Times New Roman", Times, serif;
- font-size: larger;
- color: #633;
- background-color: #eeeeee;
+ font-size: small;
+ position: relative;
}
-div#PostingHeading img
+
+.tip > div
{
- vertical-align: middle;
+ display: none;
+ position: absolute;
+ top: 25px;
+ left: auto;
+ right: 0;
+ width: 19em;
+ padding: 8px;
+ z-index: 100;
+ background: #555;
+ color: white;
+ font-style: normal;
+ text-align: left;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
}
-div#PostingHeading a
+
+.tip:hover > div
{
- text-decoration: none;
+ display: block;
}
-div#PostingFooting
+
+.tip > div > *:first-child
{
- font-size: smaller;
- background-color: #eeeeee;
+ margin-top: 0;
}
-div#PostingTOC
+.tip > div > *:last-child
{
- font-size: smaller;
+ margin-bottom: 0;
}
-div#PostingTOC li
+
+div#copyright
{
- margin-left: 0;
+ margin-top: 1.5em;
+ text-align: center;
}
-div#PostingTOC a
+
+.smallprint, .smallprint a
{
- font-family: Georgia, "Times New Roman", Times, serif;
+ color: #999;
+ font-size: small;
}
-.PostingBody /* newsgroup posting */
+
+.smallprint a:hover
{
- border: 0;
- margin: 0;
- background-color: #fcfcfc;
- color: #000066;
- margin-left: 0em;
- min-width: 15em;
- padding-bottom: 0.5em;
+ color: #555;
}
-.PostingQuote /* quote inside newsgroup posting */
+
+#contributors-github img
{
- border: 1px solid #666666;
- font-size: 90%;
- background-color: inherit;
- color: #666666;
- margin-left: 0em;
- min-width: 15em;
+ padding-right: 5px;
}
/* These are for the changelogs */
-div#version
+div.version
{
- border-top: 1px solid black;
- font-size: 0.9em;
- padding-top: 2ex;
+ font-size: 0.9em;
}
-div#version font
+div.version font
{
- font-family: Georgia, "Times New Roman", Times, serif;
- color: #633;
+ color: #633;
}
-div#version li
+div.version li
{
- padding-bottom: 0.3ex;
+ padding-bottom: 0.3ex;
}
-div#bugsfixed
+div.changelog-nav
{
+ font-size: small;
+ margin: 2em 0;
+ text-align: center;
}
-div#whatsnew
-{
+
+
+.leadingrow {
+ background-color: #E4E9EF;
+ font-size: 110%;
+}
+
+.quickindex {
+ font-weight: normal;
+ background-color: #F5F5F5;
+}
+
+.quickindex a {
+ text-decoration: none;
}
+.quickindex a:hover {
+ text-decoration: underline;
+}
-/* These are for comparison.html */
-table.comp /* "comparison with D": table */
+.question, .question *
{
- background-color:#e9e6dd;
+ display: inline;
+ text-decoration: underline;
+ cursor:pointer; /* Cursor is like a hand when someone rolls the mouse over the question */
+}
+
+.answer {
+ display:none;
+}
+
+.nobr {
+ white-space:nowrap;
+}
+
+/* Openable example boxes */
+.example-box {
+ transition: 0.25s;
+ overflow: hidden;
}
-table.comp a
+
+
+/* Runnable-examples css */
+textarea.d_code {display: none;}
+textarea.d_code_stdin, textarea.d_code_args
{
- color: black;
+ text-align: left;
+ border: none;
+ width: 98%;
+ padding: 5px;
+ margin: 1px;
+ word-wrap: break-word;
+ height: auto;
+ background: white;
+ margin-left: 2px;
+ outline: none;
+ hyphens: none;
+}
+
+pre.d_code_output {
+ border: none;
+ max-height: 30em;
+ overflow: auto;
+}
+
+div.d_code {margin: 0; padding: 0; background: #F5F5F5;}
+div.d_run_code {display: none;}
+div.d_code_output, div.d_code_stdin, div.d_code_args, div.d_code_unittest
+{
+ border: 1px solid #CCC;
+ background: white;
+ display: none;
+ height: auto;
+ width: 100%;
+}
+
+.d_code_title {font-weight: bold;padding: 5px;}
+
+pre.d_code
+{
+ overflow-x: auto;
+ white-space: pre;
+ word-wrap: unset;
+}
+
+.CodeMirror-wrap {padding: 3px;}
+.CodeMirror {line-height: normal; border: 1px solid #CCC; background: #FCFCFC; height: auto}
+.cm-s-eclipse .CodeMirror-matchingbracket {border:1px solid grey;color:black !important;}
+
+input.runButton, input.resetButton, input.argsButton, input.inputButton, input.editButton, input.openInEditorButton
+{
+ -moz-box-shadow:inset 0 1px 0 0 #ffffff;
+ -webkit-box-shadow:inset 0 1px 0 0 #ffffff;
+ box-shadow:inset 0 1px 0 0 #ffffff;
+ background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #ededed), color-stop(1, #dfdfdf) );
+ background:-moz-linear-gradient( center top, #ededed 5%, #dfdfdf 100% );
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ededed', endColorstr='#dfdfdf');
+ background-color:#ededed;
+ border:1px solid #dcdcdc;
+ display:inline-block;
+ color:#777777;
+ font-family:arial;
+ font-size:72%;
+ font-weight:bold;
+ padding:3px 6px;
+ text-decoration:none;
+ text-shadow:1px 1px 0px #ffffff;
+ width: 10en;
+ margin: 2px;
+ position: relative;
+ z-index: 2;
+ cursor: pointer;
+}
+input.openInEditorButton {
+ float: right;
+ width: auto;
}
-td.compNo /* comparison with D: "NO" */
+input.runButton:hover, input.resetButton:hover, input.argsButton:hover, input.inputButton:hover, input.editButton:hover,input.runButton[disabled]
{
- background-color:red;
- text-align:center;
+ background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #dfdfdf), color-stop(1, #ededed) );
+ background:-moz-linear-gradient( center top, #dfdfdf 5%, #ededed 100% );
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#dfdfdf', endColorstr='#ededed');
+ background-color:#dfdfdf;
}
-td.compYes /* comparison with D: "YES" */
+input.runButton:active,
+input.resetButton:active,
+input.argsButton:active,
+input.inputButton:active,
+input.editButton:active
{
- background-color:#00FF00;
- text-align:center;
+ position: relative; top: 1px;
}
+input.resetButton{display: none}
-TABLE.book
-{
- border-top: 2px solid;
- border-bottom: 2px solid;
- border-spacing: 1pt;
+div.editButton, div.openInEditorButton, div.runButton, div.resetButton {
+ display: inline-block;
+ margin-right: 10px;
+ cursor: pointer;
+ color: #333;
+ background: white;
+ border: 1px solid #CCC;
+ border-radius: 4px;
+ padding: 0.3em 0.6em;
+ display: inline-block;
+ text-decoration: none;
+}
+div.openInEditorButton {
+ margin-right: 0;
+ float: right;
+}
+div.openInEditorButton i{
+ padding-right: 5px;
+}
+.unittest_examples .d_example_buttons {
+ margin-top: 10px;
+}
+.unittest_examples .CodeMirror, .unittest_examples .d_code_output {
+ margin-top: 10px;
+}
+
+/* Style for the example run buttons on the Phobos library documentation */
+.d_example_buttons {
+ text-align: left;
+}
+.runnable-examples-stdin {
+ display: none;
+}
+.runnable-examples-args {
+ display: none;
+}
+.your-code-here-title {
+ display: none;
}
+#your-code-here-select-example {
+ padding-bottom: 0.3em;
+}
+.fa-select select {
+ background: white;
+ border: 1px solid #CCC;
+ border-radius: 4px;
+ padding: 0.3em 20px 0.3em 0.3em;
+ font-size: 0.95em;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ max-width: 120%;
+}
+.fa-select::after {
+ font-family: FontAwesome;
+ content: "\f0d7";
+ margin-left: -15px;
+ pointer-events: none; /* propagate click */
+}
+/* Runnable-examples css -end */
-TABLE.book TD
+.page-contents
{
- padding: 1pt 12pt 1pt 1pt;
- vertical-align: top;
- border-bottom: 1px solid #E4E9EF;
+ width: 300px;
+ padding-right: 10px;
+ border: solid #333;
+ border-width: 2px 0;
+ font-size: small;
+ text-align: left;
+ margin: 0 0 2em 2em;
}
-TABLE.book TH
+.page-contents-header
{
- border-bottom: 1px solid;
- padding: 1pt 12pt 1pt 1pt;
- vertical-align: top;
+ text-align: center;
}
-TABLE.book CAPTION
+.page-contents-header h3
{
- width: auto;
- text-align: left;
+ display: inline;
+ color: #444;
+ font-weight: bold;
+ margin-top: 0;
+}
+
+.page-contents li
+{
+ line-height: 1.3;
+ padding-bottom: 0;
+}
+
+@media only screen and (min-width: 66em)
+{
+ pre
+ {
+ overflow: auto;
+ }
+
+ .page-contents
+ {
+ float: right;
+ }
+}
+
+/* Narrow layout stage 1: dropdown search, dropdown subnav */
+@media only screen and (max-width: 66em)
+{
+ #top .search-container.expand-container .expand-toggle
+ {
+ display: block;
+ }
+
+ #top .expand-container > #search-box
+ {
+ background: #B03931;
+ border: 1px solid #98312A;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ display: none;
+ padding: 0.6em;
+ position: absolute;
+ top: 100%;
+ right: 0;
+ width: auto;
+ z-index: 5;
+ }
+
+ #top .expand-container.open > #search-box
+ {
+ display: block;
+ }
+
+ body#Home #content > .intro .pitch
+ {
+ width: 15em;
+ }
+
+ .subnav
+ {
+ float: none;
+ border-bottom-width: 1px;
+ border-left-width: 0;
+ border-right-width: 0;
+ margin: 0 -1em;
+ padding: 0.6em 1em;
+ width: auto;
+ }
+
+ body .subnav.expand-container > *
+ {
+ display: none;
+ }
+
+ .subnav.open
+ {
+ padding-bottom: 1em;
+ }
+
+ body.doc .subnav > ul,
+ body.std .subnav > ul > li > ul
+ {
+ -moz-column-width: 17em;
+ -webkit-column-width: 17em;
+ column-width: 17em;
+ }
+
+ body.changelog .subnav > ul
+ {
+ -moz-column-width: 10em;
+ -webkit-column-width: 10em;
+ column-width: 10em;
+ }
+
+ body.doc .subnav > ul > li,
+ body.std .subnav > ul > li > ul > li
+ {
+ /* avoid column breaks inside li */
+ -webkit-column-break-inside: avoid; /* Chrome, Safari, Opera */
+ page-break-inside: avoid; /* Firefox */
+ break-inside: avoid; /* IE 10+ */
+ }
+
+ .subnav h2
+ {
+ border-bottom-style: none;
+ margin-right: 0;
+ margin-top: 0;
+ padding-top: 1em;
+ }
+
+ /* Without JS, display the head section (h2, subhome link, ...) on one line.
+ With JS, display the toggle, and hide the other h2. */
+ .subnav > *
+ {
+ display: none;
+ }
+ .subnav > .head
+ {
+ display: block;
+ word-spacing: 1em;
+ }
+ .subnav > .head > *
+ {
+ display: inline;
+ word-spacing: 0;
+ }
+ .subnav > .head br
+ {
+ display: none;
+ }
+ .sunbav .subnav-duplicate
+ {
+ display: block;
+ }
+ .subnav > .head .separator::after
+ {
+ content: "\2013"; /* U+2013 EN DASH */
+ }
+ body.have-javascript .subnav.expand-container > .head > *,
+ body.have-javascript .subnav.expand-container.open > .head > h2,
+ body.have-javascript .subnav.expand-container.open > .head > .subnav-duplicate
+ {
+ display: none;
+ }
+
+ body.have-javascript .subnav.expand-container > h2.expand-toggle,
+ body.have-javascript .subnav.expand-container.open > .head > *,
+ body.have-javascript .subnav.expand-container > .head br
+ {
+ display: block;
+ }
+ body.have-javascript .subnav > h2.expand-toggle
+ {
+ margin: 0;
+ padding: 0;
+ }
+ body.have-javascript .head .separator::after
+ {
+ content: none;
+ }
+ body.have-javascript .subnav.open > h2
+ {
+ border-bottom-style: solid;
+ margin-bottom: 1em;
+ }
+
+ .subnav + #content
+ {
+ margin-left: 0;
+ }
+
+ .subnav-helper
+ {
+ display: none;
+ }
+
+ body#Home #content > .intro
+ {
+ padding: 0 0 1.5em;
+ }
+
+ .org_list a img
+ {
+ padding: 0.5em 2em;
+ }
+}
+
+
+/* Narrow layout stage 2: hamburger menu */
+@media only screen and (max-width:54em)
+{
+
+ #top > .helper
+ {
+ padding: 0;
+ }
+
+ /* lay out navigation vertically */
+
+ #top #cssmenu, #top #search-box
+ {
+ display: block;
+ }
+
+ #top .logo
+ {
+ width: auto;
+ }
+
+ #top .logo > a
+ {
+ background: transparent; /* override :hover background change */
+ margin-left: 1em;
+ }
+
+ #top #cssmenu, #top .search-container
+ {
+ display: none;
+ }
+
+ #top .expand-container.open #cssmenu,
+ #top .expand-container .search-container
+ {
+ display: block;
+ }
+
+ #top #cssmenu
+ {
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ border-top: 1px solid #943029;
+ clear: both;
+ }
+ #top #cssmenu > ul
+ {
+ border-bottom: 1px solid #943029;
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
+ }
+
+ #top .search-container
+ {
+ padding: 0.6em 1em;
+ width: auto;
+ }
+
+ #top .search-container.expand-container .expand-toggle
+ {
+ display: none;
+ }
+
+ #top .expand-container > #search-box
+ {
+ border: 0;
+ display: block;
+ padding: 0;
+ position: static;
+ }
+
+ #top .expand-container .search-container
+ {
+ display: none;
+ }
+
+ #top .expand-container.open .search-container
+ {
+ display: block;
+ }
+
+ #top #search-box form
+ {
+ display: table;
+ width: 100%;
+ }
+
+ #top #search-query, #top #search-dropdown, #top #search-submit
+ {
+ display: table-cell;
+ }
+
+ #top #search-query
+ {
+ width: auto;
+ }
+
+ #top #search-dropdown
+ {
+ width: 0; /* shrink to content size */
+ }
+
+ #top #cssmenu > ul > li
+ {
+ float: none;
+ }
+
+ #top #cssmenu > ul > li.expand-container.open > ul
+ {
+ border: none;
+
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+
+ position: static;
+ }
+
+ #top #cssmenu > ul > li.expand-container.open > ul > li > a
+ {
+ padding-left: 2em;
+ }
+
+ /* menu button */
+
+ #top a.hamburger
+ {
+ display: inline;
+ float: right;
+ font-size: 2em;
+ height: 1em;
+ line-height: 1;
+ padding: 0.15em 1em;
+ }
+ #top a.hamburger span
+ {
+ display: none;
+ }
+ #top a.hamburger::after
+ {
+ content: "\f0c9"; /* bars */
+ font-family: FontAwesome;
+ }
+}
+
+/* Narrow layout stage 3: no more two column boxes */
+@media only screen and (max-width: 40em)
+{
+ .boxes .row, .boxes .row .item
+ {
+ display: block;
+ padding: 0;
+ width: auto;
+ }
+}
+
+.decl_anchor {
+ visibility: hidden;
+ float: right;
+ margin-top: 5px;
+ margin-right: 5px;
+ text-decoration: none;
}
-.leadingrow {
- background-color: #E4E9EF;
- font-size: 110%;
+dt.d_decl:hover .decl_anchor {
+ visibility: visible;
}
-.d_inlinecode
-{
- font-family: "Consolas", "Bitstream Vera Sans Mono", "Andale Mono", "Monaco", "DejaVu Sans Mono", "Lucida Console", "monospace";
- /* font-size: 105%; */
- /* font-weight: bold; */
- /*color: #000010; */
+/**
+ * Vertical centering - cross-platform way
+ */
+.vcontainer-box {
+ display: block;
+}
+.vcontainer-box:before {
+ content: ' ';
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
}
-.d_decl {
- font-weight: bold;
- background-color: #E4E9EF;
- /* border-top: solid black 1px; */
- border-bottom: solid 2px #336600;
- padding: 2px 0px 2px 2px;
+.vcontainer-element {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+.center {
+ text-align: center;
+}
+
+.dont-highlight-link > a {
+ text-decoration: none;
+ color: #333;
}
-.question
+/**
+ * Version select box
+ */
+.version-changer-container {
+ float: right;
+ margin-top: -4em;
+}
+@media only screen and (max-width:40em)
{
- display: inline;
- /* font-weight:bold; /* Bold font */
- color: #006;
- text-decoration: underline;
- cursor:pointer; /* Cursor is like a hand when someone rolls the mouse over the question */
+ .version-changer-container {
+ margin-top: -2em;
+ float: none;
+ text-align: right;
+ }
}
-.answer {
- display:none;
+
+/**
+ * Messages boxes.
+ */
+.message-box {
+ padding: 1em 1em 1em 1em;
+ border-radius: 5px;
+}
+.message-box, .message-box a {
+ color: white;
+}
+.message-box-red {
+ background-color: #D60027;
+}
+.message-box-gray {
+ background-color: #797979;
+}
+.message-box-orange {
+ background-color: #EC5315;
+}
+.message-box-green {
+ background-color: #4EBA0F;
}
-.answer-nojs {
- display:block;
+.modlist-internal-separator {
+ height: 1em;
+ border-top: 1px solid #ccc;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ padding-top: 0.5em;
}
-.nobr {
- white-space:nowrap;
+/* Group related info together */
+.panel
+{
+ padding: 0.3em 0.6em;
+ border-radius: 5px;
+ background-color: #F5F5F5;
+ border: 1px solid #E6E6E6;
}
diff --git a/ctod.dd b/ctod.dd
deleted file mode 100644
index 106c40b01b..0000000000
--- a/ctod.dd
+++ /dev/null
@@ -1,1606 +0,0 @@
-Ddoc
-
-$(COMMUNITY Programming in D for C Programmers,
-
-$(COMMENT $(BLOCKQUOTE William Nerdspeare,
-Et tu, D? Then fall, C!
-))
-
-
-
-$(P 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.
-)
-
-$(P Since C does not have object-oriented features, there's a separate section
-for object-oriented issues
-Programming in D for C++ Programmers.
-)
-
-$(P The C preprocessor is covered in
-$(LINK2 pretod.html, The C Preprocessor vs D).
-)
-
-$(UL
- $(LI $(LINK2 #sizeof, Getting the Size of a Type))
- $(LI $(LINK2 #maxmin, Get the max and min values of a type))
- $(LI $(LINK2 #types, Primitive Types))
- $(LI $(LINK2 #floating, Special Floating Point Values))
- $(LI $(LINK2 #modulus, Remainder after division of floating point numbers))
- $(LI $(LINK2 #nans, Dealing with NANs in floating point compares))
- $(LI $(LINK2 #assert, Asserts))
- $(LI $(LINK2 #arrayinit, Initializing all elements of an array))
- $(LI $(LINK2 #arrayloop, Looping through an array))
- $(LI $(LINK2 #arraycreate, Creating an array of variable size))
- $(LI $(LINK2 #strcat, String Concatenation))
- $(LI $(LINK2 #printf, Formatted printing))
- $(LI $(LINK2 #forwardfunc, Forward referencing functions))
- $(LI $(LINK2 #funcvoid, Functions that have no arguments))
- $(LI $(LINK2 #labeledbreak, Labeled break and continue statements))
- $(LI $(LINK2 #goto, Goto Statements))
- $(LI $(LINK2 #tagspace, Struct tag name space))
- $(LI $(LINK2 #stringlookup, Looking up strings))
- $(LI $(LINK2 #align, Setting struct member alignment))
- $(LI $(LINK2 #anonymous, Anonymous Structs and Unions))
- $(LI $(LINK2 #declaring, Declaring struct types and variables))
- $(LI $(LINK2 #fieldoffset, Getting the offset of a struct member))
- $(LI $(LINK2 #unioninit, Union initializations))
- $(LI $(LINK2 #structinit, Struct initializations))
- $(LI $(LINK2 #arrayinit2, Array initializations))
- $(LI $(LINK2 #stringlit, Escaped String Literals))
- $(LI $(LINK2 #ascii, Ascii vs Wide Characters))
- $(LI $(LINK2 #arrayenum, Arrays that parallel an enum))
- $(LI $(LINK2 #typedefs, Creating a new type with typedef))
- $(LI $(LINK2 #structcmp, Comparing structs))
- $(LI $(LINK2 #stringcmp, Comparing strings))
- $(LI $(LINK2 #sort, Sorting arrays))
- $(LI $(LINK2 #volatile, Volatile memory access))
- $(LI $(LINK2 #strings, String literals))
- $(LI $(LINK2 #traversal, Data Structure Traversal))
- $(LI $(LINK2 #ushr, Unsigned Right Shift))
- $(LI $(LINK2 #closures, Dynamic Closures))
- $(LI $(LINK2 #variadic, Variadic Function Parameters))
-)
-
-
-Getting the Size of a Type
-
-The C Way
-
-$(CCODE
-sizeof(int)
-sizeof(char *)
-sizeof(double)
-sizeof(struct Foo)
-)
-
-The D Way
-
-Use the size property:
-
-----------------------------
-int.sizeof
-(char *).sizeof
-double.sizeof
-Foo.sizeof
-----------------------------
-
-
-Get the max and min values of a type
-
-The C Way
-
-$(CCODE
-#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
-
-$(CCODE
-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 => ireal
-_Complex long double => creal
-)
-
- 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
-
-$(CCODE
-#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
-
-$(CCODE
-#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 NANs 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).
-
-$(CCODE
-#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
-----------------------------
-
-
-Asserts 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__.
-
-$(CCODE
-#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
-
-$(CCODE
-#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.
-
-$(CCODE
-#define ARRAY_LENGTH 17
-int array[ARRAY_LENGTH];
-for (i = 0; i < ARRAY_LENGTH; i++)
- func(array[i]);
-)
-
-or:
-
-$(CCODE
-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 through 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:
-
-$(CCODE
-#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 freed, dealing with null pointers,
- finding the length of the strings, and memory allocation:
-
-$(CCODE
-#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:
-
-$(CCODE
-#include <stdio.h>
-
-printf("Calling all cars %d times!\n", ntimes);
-)
-
-The D Way
-
- What can we say? printf() rules:
-
-----------------------------
-printf("Calling all cars %d times!\n", ntimes);
-----------------------------
-
- writefln() improves on printf() by being type-aware and type-safe:
-
------------------------
-import std.stdio;
-
-writefln("Calling all cars %s times!", 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.
-
-$(CCODE
-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
-
-$(CCODE
-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()
-{
- ...
-}
-----------------------------
-
-
-Labeled break and continue statements
-
-The C Way
-
- Break and continue statements only apply to the innermost nested loop or
- switch, so a multilevel break must use a goto:
-
-$(CCODE
- 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
- labeled
- 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 goto statements.
-
-
-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:
-
-$(CCODE
-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.
-
-$(CCODE
-#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, $(D #pragma)s are used:
-
-$(CCODE
-#pragma pack(1)
-struct ABC
-{
- ...
-};
-#pragma pack()
-)
-
- But $(D #pragma)s are nonportable both in theory and in practice from
- compiler to compiler.
-
-The D Way
-
- $(P D has a syntax for setting the alignment that is common
- to all D compilers. The actual alignment done is compatible
- with the companion C compiler's alignment, for ABI compatibility.
- To match a particular layout across architectures, use
- $(D align(1)) and manually specify it.
- )
-
-----------------------------
-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:
-
-$(CCODE
-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
-
- $(P Is to do it in one statement ending with a semicolon:)
-
-$(CCODE
-struct Foo { int x; int y; } foo;
-)
-
- $(P Or to separate the two:)
-
-$(CCODE
-struct Foo { int x; int y; }; // note terminating ;
-struct Foo foo;
-)
-
-The D Way
-
- $(P 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;
-----------------------------
-
- $(P 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:
-
-$(CCODE
-#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.offsetof;
-----------------------------
-
-
-Union Initializations
-
-The C Way
-
- Unions are initialized using the "first member" rule:
-
-$(CCODE
-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:
-
-$(CCODE
-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:
-$(CCODE
-int a[3] = { 3,2,2 };
-)
- Nested arrays may or may not have the { }:
-$(CCODE
-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:
-$(CCODE
-char file[] = "c:\\root\\file.c";
-)
-This gets even more unpleasant with regular expressions.
-Consider the escape sequence to match a quoted string:
-$(CCODE
-/"[^\\]*(\\.[^\\]*)*"/
-)
-In C, this horror is expressed as:
-$(CCODE
-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:
-$(CCODE
-#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:
-$(CCODE
-#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:
-$(CCODE
-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 type with typedef
-
-The C Way
-
- Typedefs 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.
-
-$(CCODE
-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.
-
-$(CCODE
-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:
-
-$(CCODE
-#define HANDLE_INIT ((Handle)-1)
-
-Handle h = HANDLE_INIT;
-h = func();
-if (h != HANDLE_INIT)
- ...
-)
-
- For the struct solution, things get even more complex:
-
-$(CCODE
-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: $(D 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 $(D .init) property:
-
------------------------------
-typedef void* Handle = cast(void*)(-1);
-Handle h;
-h = func();
-if (h != Handle.init)
- ...
------------------------------
-
- There's only one name to remember: $(D Handle).
-
-
-Comparing structs
-
-The C Way
-
- While C defines struct assignment in a simple, convenient manner:
-
-$(CCODE
-struct A x, y;
-...
-x = y;
-)
-
- it does not for struct comparisons. Hence, to compare two struct
- instances for equality:
-
-$(CCODE
-#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:
-$(CCODE
-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():
-
-$(CCODE
-int compare(const void *p1, const void *p2)
-{
- type *t1 = (type *)p1;
- type *t2 = (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:
-$(CCODE
-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:
-
-$(CCODE
-"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 $(D 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 $(D struct Paramblock)
- is created and a pointer to it is used to maximize efficiency.
-
-$(CCODE
-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:
-
-$(CCODE
-int i, j;
-...
-j = (unsigned)i >> 3;
-)
-
- If $(D i) is an $(D int), this works fine. But if $(D i) is
- of a type created with typedef,
-
-$(CCODE
-myint i, j;
-...
-j = (unsigned)i >> 3;
-)
-
- and $(D myint) happens to be a $(D 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 $(I 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
- $(D void *p). The example here is of a trivial container
- class that holds an array of ints, and a user of that container
- that computes the maximum of those ints.
-
-$(CCODE
-void apply(void *p, int *array, int dim, void (*fp)(void *, int))
-{
- for (int i = 0; i < dim; i++)
- fp(p, array[i]);
-}
-
-struct Collection
-{
- int array[10];
-};
-
-void comp_max(void *p, int i)
-{
- int *pmax = (int *)p;
-
- if (i > *pmax)
- *pmax = i;
-}
-
-void func(struct Collection *c)
-{
- int max = INT_MIN;
-
- apply(&max, c->array, sizeof(c->array)/sizeof(c->array[0]), comp_max);
-}
-)
-
- $(P While this works, it isn't very flexible.)
-
-
The D Way
-
- The D version makes use of $(I delegates) to transmit
- context information for the $(I apply) function,
- and $(I 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 $(I 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
-
-$(CCODE
-#include <stdio.h>
-#include <stdarg.h>
-
-int $(B 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 = $(B sum)(3, 8,7,6);
- printf("sum = %d\n", i);
-
- return 0;
-}
-)
-
- There are two problems with this. The first is that the
- $(D 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:
-
------------------------------
-import std.stdio;
-
-int $(B sum)(int[] values ...)
-{
- int s = 0;
-
- foreach (int x; values)
- s += x;
- return s;
-}
-
-int main()
-{
- int i;
-
- i = $(B sum)(8,7,6);
- writefln("sum = %d", i);
-
- return 0;
-}
------------------------------
-)
-
-Macros:
- TITLE=Programming in D for C Programmers
- WIKI=ctod
- CATEGORY_OVERVIEW=$0
diff --git a/d-keyring.gpg b/d-keyring.gpg
new file mode 100644
index 0000000000..f83945bc55
Binary files /dev/null and b/d-keyring.gpg differ
diff --git a/d-keyring.gpg.sig b/d-keyring.gpg.sig
new file mode 100644
index 0000000000..825a479799
Binary files /dev/null and b/d-keyring.gpg.sig differ
diff --git a/d-security.asc b/d-security.asc
new file mode 100644
index 0000000000..0beed48c63
--- /dev/null
+++ b/d-security.asc
@@ -0,0 +1,63 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFs+Y9YBEADVO7yaz+dFWq1Rioas+bfX07VC5X/dBNY/bRHPSE3k196+wHqs
+j1jEigg0BDpR4bYBZeHlv65cFWu6SABLXBV7Y99kz2vCfJFRbEvDsW3dl3PYIIKM
+8kASwDEy/xmHUvYOsg8rzoWqQHApTp9HHarq6cyN5QECJIeAdwNali67wd8Q3hYJ
+QSspjgtSIdVNWsEXBvPJjZXE/hsYKs8uZcx5p30fCyz96uRI6/z307WNU8yXy8Co
+HyyJBH68Gnbw0bYjU6NYpDZfgAbStdlU2vd0XYSWjWxcR3aqzqyWOt7gTtiCWD9I
+dshMGpGnqglHt/uvayr9K4uQZ6fpY2hGuw8z7rPzPN5KFSpDaznBBZqIzKFb1s/O
+/9pu3ejH0n24sFIyf83HM7M2NxBb7+krKObjSrUYrzs5mReNwTvKbzWlz03PY6Pr
+FafKbhC2jO/15VppZBWXZP4tF5Zpz7QG6kBNn1buPteUQ+X1wL5QXUAjsS/OvQM/
+ctLZSMADVGRyiTnMdNMP7pJ1gTUXPv3zW6JLzJQ3SLcHj9oke71bJWd5wTV2kXHl
+GLIkKHiVR9G9o2CZqWkdDJXpYT1UYwOEqlKai8iqVmyIOi8gwBo7xhYfxDEDNHOy
+Iz2ie1lG/l5sy9qmeSt32Gr4YSfW2xujwuLpaQsWkeUSYrwZogW+Tla3owARAQAB
+tChETGFuZyBTZWN1cml0eSBUZWFtIDxzZWN1cml0eUBkbGFuZy5vcmc+iQJFBBMB
+CgAvFiEE4Fqzww7Ax91W2ZsMj/BJspY47dIFAls+Y9YCGwMFCQPCZwACFQoCHgEC
+F4AACgkQj/BJspY47dKL7w//dfj9bg8XZimrp0JQ3FAlTuwb1AevpTkscln+gbzA
+jlNNOFrZHWw7FaKbPCKMc0n+8yNiVRpBEZSQ7QsTRkqvYNuHL/lWPH5kRjk1FW8a
+hDxgaAt7cV8DhPyfXM3OO0KnTAVzW89hfIVlMXHiQYJZynmFRV3R1VJnVfMGBbqn
+PP2XZAcV0FITX2FAY0AUjGIKFfKzN5WkmX8MhZd6+8gX+7VWVlQJJS6/9INwf5JX
+Hfh0WxygycT4WOghQxcsc7YEmhnfpwvKOQVppqvE4FDi48HFhS8cXtqQ3oQJnLAt
+fgAjFx49gOZ+CoigpgaRqDjeAt5fF8MJcjcGjjA6HeXzrcr/85HM5r8PUPPZnjFe
+4s/6MrKduIEdy6F1heQEmOf/ywAYW6Om0GCkfuk6rDxp/5wMStLmKQjNJril6TLt
+lX1V4A+Kmjw/JWDXS9obxO7xWf0KVqTYKB4dHyyvflqGge3uDuhl1XYzE7ad9hib
+4p2hXSJbAvgXnvFiII+1fHtpyu1aAvPVeZgaWsMQnps2sfDg0W8lU8Ae5BRBbYHb
+gO+dJ3UikGTLHTv1hfw7TvvZvNoDyjN0in+NqzBdWW4MCG1hZ91DYwXF1F8htXjd
+jUUmqocjVduPeqRrrPhVGgYHlfSiluWC6aWtwTzBhO7uu9T4o70o45DWHnJRjKK1
+7ruJAjMEEAEKAB0WIQSP2401evRoqUKKzjwgVfdmAaNvsAUCW0R8NAAKCRAgVfdm
+AaNvsFsYD/9O3R+ZsxcZ2Pe6iFBQqmZ72H/io6ZQCk0Ue5ehb9t28n6C1V3Q50Ox
+XsZWmPD9/97QjVXWkMHPg7/kdtq8a+StN6/MIFPs3kwgCedsm7BFYY1QrJMvdBu7
++sI3uz12OP4PcFKJZuYO0AygtaZVrpumzOgo5rh2Lvn1OFQoW10KcZutwdVDGJwY
+jfpF13ol7dIvtnpZUIBw3uznxI+xqGLDaeJ22dYF0SZAhFGlDwTEy7QKqUdlHS3D
+KJlGJ1eKs1HA2Slo4ZGrwVBhzFfkKKLbuhH3AH+CF88sVExVRW4+j3a0LU6//YvJ
+sVeNx9mbKeYmeZEXOJoR4/+A90e81+oHbxQhbTfIjokrrSFtKwkrgEvH7OkZxux8
+MrStsuq7X5xRUeXnggmw2jR/8hLcjLBz52928/RBOL2aE+WxU/heDe8GbkXryFzG
+jqb3KAAPX1r3LuKWVs+trKuO/uDkU1tF1aDHCzq63P2pkgPmxILkrZvSri4ADUzs
+CZppcux1Ee8rYEAd3YfFnXXifk0sXBGkHW0QJ5HYYbi82zmHZiOH9veosza8cvOv
+D6KofSM2HXki8GIBB4tqqPsIPPPVywfV48mnSnmJRXWy4TSE4IvzVAH7VGf4EBq8
+9xA3NORQwotgPT8ZAv2n7Bo3sFTQ+LK7MQt2MSOt74Ca0Q6yieNdzbkCDQRbPmPW
+ARAAxvUWetoIbQunoKOK8FJfx1AazxUQWT0LlQl0UPfFL5+zqGm86T9Lye3aiywN
+MgwacVnh5CZXRb/XU4JibkVgUji3RQ2vnrqETfg0mfzHe7v2Wd/m0R3ijltTR3/z
+ZEJxfiRiBR8bUZuVgsyDxyneTlne88SiAdQIRbcoxWDrSIbm9HMubYNQfbDOHSjB
+Z0kvkFdU3smu+sl8EM2/FhlWJ2+Tdf0YzKsq7QQAUjP7XdcHg+2UjcPlLBY+eCQS
+/i/N8brN4YsJR2N0DH3lYQEJuEhLEQUW2DKbUga0mJsyOutAUEAnbbxub5h4Y2AT
+qztX1SCGuyuac5fgL8TbOSBDMYwdUCoWLPt8xlWC+jfvBubSc3lM9bdYU8bauxtv
+skNY6MMM2OUFDBUaiXdrfWy/bwou5iJOdLJnxEUHOZl8jPqJUrMuD6yBACHaMtLi
+T2Lx/nuxLGgEIWvP5tGBYV815knySaGYkZMpujkDhRFVzAqd+O8AakM2RZJ4Fmzc
+i5Mi6GdAo5O3QXcKvrrO2XdF9Jq6cnqWF31X926YpCZiYP8+Fk6C1ekjRu99/tdP
+wBZtptBJGoeshF9bhkR/vC/ArQWIhVlwM9mzj4i5RKCnVQZhj4to3rrnyBU2eg8O
+WPTqosHl9MkQIgxtYtDWlvF0uhuSX3AsVyx0Gjw8DgjdxtsAEQEAAYkCPAQYAQoA
+JhYhBOBas8MOwMfdVtmbDI/wSbKWOO3SBQJbPmPWAhsMBQkDwmcAAAoJEI/wSbKW
+OO3S1p4P/RJSRx2XqThbTMVbnmayE0Le/pys1623xMfjOKedm2UUvCXlsnG1EMNU
+M0roAUTT9SgdAsAF68lI94tyACOS6vfvSyzv0Nb61CbXNT3saGIOvoN6lpflsBcS
+jZZZf4f8vOdw7FLqHU6n9qX24elLJuainV2VA+8zgiiTyfyepDnjRGij1AUc3s31
+2nIYZzRbF+5A+loGYhpunptBkrOPEVAaBT0mf6Ko5nH+7obm+2oXnGJvd3S3K2Ay
+58C33/C7Gd6NTHW+wXL7Qb09OQfnLSZS2za6wFhNXDXzvJDGLzuGBwXDKT6DcBPm
+fufL1V+sTnyt+LMs4hz/XeV6JWqLFeh102JcFeBBtI4B+eDNsl+4cHS5POWQPWNU
+2dXdvJPkO48hKMslQP7VG6SWzOcorFERG0CgDWFfgSir2wIzhnyNu0LJypoMhAZQ
+U+aEjW6NN4Hj/dPhow9GF7BSUAx3kYkx8prC7dtaP52Q3eu46h+4gFpdnvhOwDQo
+XbJ2uK4e44oTiK4p6KM6KJ4SGe0rDkJxdMAyQqxgZ+06MldSbfQr3oAHV0q4QgSj
+xZ4FXaKR/Bf8S1s5pffuTCLgihjRl9lW9N5L9cb8TN898ZyZ/1QREJNdtyar+g/j
+C48HmPXN4MzQZZahw44rAUcbk2QSlFO3jj0rfY/HkOch3TU8lLOZ
+=42J0
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/dbc.dd b/dbc.dd
deleted file mode 100644
index c5aef0de6a..0000000000
--- a/dbc.dd
+++ /dev/null
@@ -1,167 +0,0 @@
-Ddoc
-
-$(SPEC_S 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:
-
- $(OL
- $(LI a consistent look and feel for the contracts)
- $(LI tool support)
- $(LI it's possible the compiler can generate better code using information gathered
- from the contracts)
- $(LI easier management and enforcement of contracts)
- $(LI handling of contract inheritance)
- )
-
-$(COMMENT
)
-
- $(P 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
- $(GLINK2 expression, AssertExpression).
- An $(B 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 AssertError,
- 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 AssertError is thrown. If a post contract fails,
- then there is a bug in the body. An AssertError 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 && (result+1) * (result+1) >= x);
- }
- body
- {
- return cast(long)std.math.sqrt(cast(real)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, $(I result) is initialized and set to the
- return value of the function.
-
-
In, Out and Inheritance
-
- $(P If a function in a derived class overrides a function in its
- super class, then only one of
- the $(D in) contracts of the function and its base functions
- must be satisfied.
- Overriding
- functions then becomes a process of $(I loosening) the $(D in)
- contracts.
- )
-
- $(P A function without an $(D in) contract means that any values
- of the function parameters are allowed. This implies that if any
- function in an inheritance hierarchy has no $(D in) contract,
- then $(D in) contracts on functions overriding it have no useful
- effect.
- )
-
- $(P Conversely, all of the $(D out) contracts needs to be satisfied,
- so overriding functions becomes a processes of $(I tightening) the
- $(D out)
- contracts.
- )
-
-Class Invariants
-
- $(P 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 $(DDLINK class, Classes, Classes).
- )
-
-References
-
- $(LIST
- $(LINK2 http://people.cs.uchicago.edu/~robby/contract-reading-list/, Contracts Reading List),
- $(LINK2 http://jan.newmarch.name/java/contracts/paper-long.html, Adding Contracts to Java)
- )
-
-)
-
-Macros:
- TITLE=Contract Programming
- WIKI=DBC
- CATEGORY_SPEC=$0
-
diff --git a/dblog_feed_example.xml b/dblog_feed_example.xml
new file mode 100644
index 0000000000..c2dbcafc2f
--- /dev/null
+++ b/dblog_feed_example.xml
@@ -0,0 +1,167 @@
+
+
+
+
+ The D Blog
+
+ https://dlang.org/blog
+ The official blog for the D Programming Language.
+ Mon, 19 Mar 2018 13:27:32 +0000
+ en-US
+ hourly
+ 1
+ https://wordpress.org/?v=4.9.4
+112438176 -
+
DConf 2018 Programme & Open Registration
+ https://dlang.org/blog/2018/03/19/dconf-2018-programme-open-registration/
+ https://dlang.org/blog/2018/03/19/dconf-2018-programme-open-registration/#respond
+ Mon, 19 Mar 2018 13:27:32 +0000
+
+
+
+
+ http://dlang.org/blog/?p=1493
+
+ https://dlang.org/blog/2018/03/19/dconf-2018-programme-open-registration/feed/
+ 0
+ 1493
+ -
+
User Stories: Funkwerk
+ https://dlang.org/blog/2018/03/14/user-stories-funkwerk/
+ https://dlang.org/blog/2018/03/14/user-stories-funkwerk/#comments
+ Wed, 14 Mar 2018 14:06:32 +0000
+
+
+
+
+
+
+
+ http://dlang.org/blog/?p=1479
+
+ https://dlang.org/blog/2018/03/14/user-stories-funkwerk/feed/
+ 3
+ 1479
+ -
+
The D Language Foundation at Open Collective
+ https://dlang.org/blog/2018/03/12/the-d-foundation-at-open-collective/
+ https://dlang.org/blog/2018/03/12/the-d-foundation-at-open-collective/#respond
+ Mon, 12 Mar 2018 14:20:54 +0000
+
+
+
+
+ http://dlang.org/blog/?p=1441
+
+ https://dlang.org/blog/2018/03/12/the-d-foundation-at-open-collective/feed/
+ 0
+ 1441
+ -
+
The New New DIP Process
+ https://dlang.org/blog/2018/03/09/the-new-new-dip-process/
+ https://dlang.org/blog/2018/03/09/the-new-new-dip-process/#comments
+ Fri, 09 Mar 2018 12:49:07 +0000
+
+
+
+
+ http://dlang.org/blog/?p=1437
+
+ https://dlang.org/blog/2018/03/09/the-new-new-dip-process/feed/
+ 3
+ 1437
+ -
+
LDC 1.8.0 Released
+ https://dlang.org/blog/2018/03/06/ldc-1-8-0-released/
+ https://dlang.org/blog/2018/03/06/ldc-1-8-0-released/#respond
+ Tue, 06 Mar 2018 13:56:15 +0000
+
+
+
+
+
+
+ http://dlang.org/blog/?p=1428
+
+ https://dlang.org/blog/2018/03/06/ldc-1-8-0-released/feed/
+ 0
+ 1428
+ -
+
DMD 2.079.0 Released
+ https://dlang.org/blog/2018/03/03/dmd-2-079-0-released/
+ https://dlang.org/blog/2018/03/03/dmd-2-079-0-released/#respond
+ Sat, 03 Mar 2018 12:00:30 +0000
+
+
+
+
+
+
+
+ http://dlang.org/blog/?p=1408
+
+ https://dlang.org/blog/2018/03/03/dmd-2-079-0-released/feed/
+ 0
+ 1408
+ -
+
The State of D 2018 Survey
+ https://dlang.org/blog/2018/02/28/the-state-of-d-2018-survey/
+ https://dlang.org/blog/2018/02/28/the-state-of-d-2018-survey/#respond
+ Wed, 28 Feb 2018 13:30:49 +0000
+
+
+
+
+
+
+ http://dlang.org/blog/?p=1400
+
+ https://dlang.org/blog/2018/02/28/the-state-of-d-2018-survey/feed/
+ 0
+ 1400
+ -
+
DConf 2018 Munich: The Venue
+ https://dlang.org/blog/2018/02/23/dconf-2018-munich-the-venue/
+ https://dlang.org/blog/2018/02/23/dconf-2018-munich-the-venue/#respond
+ Fri, 23 Feb 2018 13:38:00 +0000
+
+
+
+
+ http://dlang.org/blog/?p=1386
+
+ https://dlang.org/blog/2018/02/23/dconf-2018-munich-the-venue/feed/
+ 0
+ 1386
+ -
+
Project Highlight: The D Community Hub
+ https://dlang.org/blog/2018/02/17/project-highlight-the-d-community-hub/
+ https://dlang.org/blog/2018/02/17/project-highlight-the-d-community-hub/#respond
+ Sat, 17 Feb 2018 12:46:19 +0000
+
+
+
+
+
+ http://dlang.org/blog/?p=1381
+ dlang-community organization at GitHub.]]>
+ https://dlang.org/blog/2018/02/17/project-highlight-the-d-community-hub/feed/
+ 0
+ 1381
+ -
+
Vanquish Forever These Bugs That Blasted Your Kingdom
+ https://dlang.org/blog/2018/02/07/vanquish-forever-these-bugs-that-blasted-your-kingdom/
+ https://dlang.org/blog/2018/02/07/vanquish-forever-these-bugs-that-blasted-your-kingdom/#comments
+ Wed, 07 Feb 2018 13:07:26 +0000
+
+
+
+
+
+ http://dlang.org/blog/?p=1350
+
+ https://dlang.org/blog/2018/02/07/vanquish-forever-these-bugs-that-blasted-your-kingdom/feed/
+ 4
+ 1350
+
+
diff --git a/dcompiler.dd b/dcompiler.dd
index 3e2c8f6be2..6029715d2d 100644
--- a/dcompiler.dd
+++ b/dcompiler.dd
@@ -2,807 +2,698 @@ Ddoc
$(D_S dmd - $(WINDOWS Windows)$(LINUX Linux)$(OSX Mac OS X)$(FREEBSD FreeBSD) D Compiler,
- $(UL
- $(WINDOWS $(LI dmd for $(LINK2 dmd-linux.html, Linux)))
- $(WINDOWS $(LI dmd for $(LINK2 dmd-osx.html, OSX)))
- $(WINDOWS $(LI dmd for $(LINK2 dmd-freebsd.html, FreeBSD)))
- $(LINUX $(LI dmd for $(LINK2 dmd-windows.html, Windows)))
- $(LINUX $(LI dmd for $(LINK2 dmd-osx.html, OSX)))
- $(LINUX $(LI dmd for $(LINK2 dmd-freebsd.html, FreeBSD)))
- $(OSX $(LI dmd for $(LINK2 dmd-windows.html, Windows)))
- $(OSX $(LI dmd for $(LINK2 dmd-linux.html, Linux)))
- $(OSX $(LI dmd for $(LINK2 dmd-freebsd.html, FreeBSD)))
- $(FREEBSD $(LI dmd for $(LINK2 dmd-windows.html, Windows)))
- $(FREEBSD $(LI dmd for $(LINK2 dmd-linux.html, Linux)))
- $(FREEBSD $(LI dmd for $(LINK2 dmd-osx.html, OSX)))
- $(LI $(LINK2 #requirements, Requirements and Downloads))
- $(LI $(LINK2 #files, Files))
- $(LI $(LINK2 #installation, Installation))
- $(WINDOWS $(LI $(LINK2 #example, Example)))
- $(LI $(LINK2 #switches, Compiler Arguments and Switches))
- $(LI $(LINK2 #linking, Linking))
- $(LI $(LINK2 #environment, Environment Variables))
- $(WINDOWS $(LI $(LINK2 #sc_ini, sc.ini Initialization File)))
- $(UNIX $(LI $(DMD_CONF) Initialization File))
- $(WINDOWS $(LI $(LINK2 #problems, Common Installation Problems)))
- $(LI $(LINK2 #differences, Differences between Windows and Linux versions))
- $(LI $(LINK2 #interface_files, D Interface Files))
- $(LI $(LINK2 #library, Building Libraries))
- $(LI $(LINK2 #compiling_dmd, Compiling dmd))
- $(LI $(LINK2 #compiling_phobos, Compiling Phobos))
- )
-
-$(LNAME2 requirements, Requirements and Downloads)
-
- $(OL
- $(LI $(LINK2 http://www.digitalmars.com/d/download.html, Download D Compiler))
+ $(UL
+ $(LI $(RELATIVE_LINK2 requirements, Requirements and Downloads))
+ $(LI $(RELATIVE_LINK2 installation, Installation))
+ $(WINDOWS $(LI $(RELATIVE_LINK2 example, Example)))
+ $(LI $(RELATIVE_LINK2 switches, Compiler Arguments and Switches))
+ $(LI $(RELATIVE_LINK2 files, Files))
+ $(LI $(RELATIVE_LINK2 linking, Linking))
+ $(LI $(RELATIVE_LINK2 environment, Environment Variables))
+ $(WINDOWS $(LI $(RELATIVE_LINK2 sc-ini, sc.ini Initialization File)))
+ $(UNIX $(LI $(DMD_CONF) Initialization File))
+ $(WINDOWS $(LI $(RELATIVE_LINK2 problems, Common Installation Problems)))
+ $(LI $(RELATIVE_LINK2 differences, Differences between Windows and Linux versions))
+ $(LI $(RELATIVE_LINK2 interface-files, D Interface Files))
+ $(LI $(RELATIVE_LINK2 library, Building Libraries))
+ $(LI $(RELATIVE_LINK2 compiling-dmd, Compiling dmd))
+ $(LI $(RELATIVE_LINK2 compiling-phobos, Compiling Phobos))
+ )
+
+$(H2 $(LNAME2 requirements, Requirements and Downloads))
+
+ $(OL
+ $(LI $(LINK2 https://dlang.org/download.html, DMD Compiler))
$(WINDOWS
- $(LI 32 bit Windows (Win32) operating system, such as Windows XP)
+ $(LI Windows operating system, Windows 7 or later, 32 or 64 bit)
- $(LI Download
-
- dmc.zip (C and C++ compiler) for Win32
- (not required, but it complements dmd for Windows)
- )
+ $(LI Download
+
+ dmc.zip (C and C++ compiler) for Win32
+ (not required, but it complements dmd for Windows)
+ )
)
$(LINUX
- $(LI 32 bit x86 and 64 bit x86-64 Linux operating system)
+ $(LI 32 bit x86 and 64 bit x86-64 Linux operating system
+ ($(LINK2 https://github.com/ldc-developers/ldc, LDC)
+ and $(LINK2 https://github.com/D-Programming-GDC/GDC, GDC)
+ provide support for more architectures)
+ )
- $(LI Gnu C compiler (gcc))
+ $(LI Gnu C compiler (gcc) or LLVM C compiler (clang))
)
$(OSX
- $(LI 32 bit x86 Mac OSX operating system)
+ $(LI Mac OS X Mavericks (10.9) or later)
- $(LI Gnu C compiler (gcc))
+ $(LI Xcode)
)
$(FREEBSD
- $(LI 32 bit x86 FreeBSD 7.1 operating system)
+ $(LI 32 bit x86 and 64 bit x86-64 FreeBSD operating system (11 or later))
- $(LI Gnu C compiler (gcc))
+ $(LI Gnu C compiler (gcc))
+ )
)
- )
-
-$(LNAME2 files, Files)
-
- $(DL
-
- $(DT $(D $(DMDDIR)$(SEP)src$(SEP)phobos$(SEP))
- $(DD D runtime library source)
- )
-
- $(DT $(D $(DMDDIR)$(SEP)src$(SEP)dmd$(SEP))
- $(DD D compiler front end source under dual (GPL and Artistic) license)
- )
- $(DT $(D $(DMDDIR)$(SEP)html$(SEP)d$(SEP))
- $(DD Documentation)
- )
+$(H2 $(LNAME2 installation, Installation))
- $(DT $(D $(DMDDIR)$(SEP)samples$(SEP)d$(SEP))
- $(DD Sample D programs)
- )
$(WINDOWS
- $(DT $(D $(DMDDIR)\windows\bin\dmd.exe)
- $(DD D compiler executable)
- )
-
- $(DT $(D $(DMDDIR)\windows\bin\$(LINK2 http://www.digitalmars.com/ctg/shell.html, shell.exe))
- $(DD Simple command line shell)
- )
+$(MESSAGE_BOX gray, $(B Hint) - The official $(LINK2 $(ROOT_DIR)download.html, installer)
+performs these steps automatically.
+)
+ $(P Open a console window (for Windows 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.
+ $(D dmd.zip) will create
+ a $(D $(DMDDIR)) directory with all the files in it.
+ $(D dmc.zip) will create
+ a $(D \dm) directory with all the files in it.
+ )
- $(DT $(D $(DMDDIR)\windows\bin\sc.ini)
- $(DD Global compiler settings)
- )
+ $(P A typical session might look like:)
- $(DT $(D $(DMDDIR)\windows\lib\$(LIB))
- $(DD D runtime library)
- )
+$(CONSOLE
+C:\Documents and Settings\Your Name>cd \
+C:\\>unzip dmd.zip
+C:\\>unzip dmc.zip
+)
)
$(LINUX
- $(DT $(D $(DMDDIR)/linux/bin/dmd)
- $(DD D compiler executable)
- )
- $(DT $(D $(DMDDIR)/linux/bin/$(DUMPOBJ))
- $(DD Elf file dumper)
- )
+ $(INSTALLATION_SCRIPT_HINT)
- $(DT $(D $(DMDDIR)/linux/bin/$(OBJ2ASM))
- $(DD Elf file disassembler)
- )
+ Unzip the archive into your home directory.
+ It will create a $(D ~/dmd) directory with all the files in it.
- $(DT $(D $(DMDDIR)/linux/bin/$(SHELL))
- $(DD Simple command line shell)
- )
-
- $(DT $(D $(DMDDIR)/linux/bin/$(DMD_CONF))
- $(DD Global compiler settings (copy to $(D /etc/dmd.conf)))
- )
+ All the tools are command line tools, which means
+ they are run from a console window.
+ All tools can be run directly from the archive:
+$(CONSOLE
+~/dmd/linux/bin64/dmd
+)
+ To install $(D dmd) globally, add the `~/dmd/linux/bin64` folder to your $(B PATH).
+$(CONSOLE
+export PATH="$HOME/dmd/linux/bin64:$PATH"
+)
- $(DT $(D $(DMDDIR)/linux/lib/$(LIB))
- $(DD D runtime library (copy to $(D /usr/lib/$(LIB))))
- )
- )
- $(FREEBSD
- $(DT $(D $(DMDDIR)/freebsd/bin/dmd)
- $(DD D compiler executable)
- )
+ Alternatively, you can install dmd locally yourself by:
+ $(P $(UL
- $(DT $(D $(DMDDIR)/freebsd/bin/$(DUMPOBJ))
- $(DD Elf file dumper)
- )
+ $(LI Create a configuration file in $(D /etc/dmd.conf):
- $(DT $(D $(DMDDIR)/freebsd/bin/$(OBJ2ASM))
- $(DD Elf file disassembler)
- )
+---
+[Environment64]
+DFLAGS=-I/usr/local/include/d/dmd -L-L/usr/local/lib -L--export-dynamic -fPIC
+---
- $(DT $(D $(DMDDIR)/freebsd/bin/$(SHELL))
- $(DD Simple command line shell)
- )
+ )
- $(DT $(D $(DMDDIR)/freebsd/bin/$(DMD_CONF))
- $(DD Global compiler settings (copy to $(D /etc/dmd.conf)))
- )
+ $(LI Copy binaries to $(D /usr/local/bin):
- $(DT $(D $(DMDDIR)/freebsd/lib/$(LIB))
- $(DD D runtime library (copy to $(D /usr/lib/$(LIB))))
- )
+$(CONSOLE
+sudo cp $(DMDDIR)/linux/bin64/{dmd,$(DUMPOBJ),$(OBJ2ASM),rdmd,ddemangle,dub,dustmite} /usr/local/bin
+)
)
- $(OSX
- $(DT $(D $(DMDDIR)/osx/bin/dmd)
- $(DD D compiler executable)
- )
- $(DT $(D $(DMDDIR)/osx/bin/$(DUMPOBJ))
- $(DD Mach-O file dumper)
- )
+ $(LI Copy the library to $(D /usr/local/lib):
- $(DT $(D $(DMDDIR)/osx/bin/$(OBJ2ASM))
- $(DD Mach-O file disassembler)
- )
+$(CONSOLE
+sudo cp $(DMDDIR)/linux/lib64/$(LIB) /usr/local/lib
+)
+ )
- $(DT $(D $(DMDDIR)/osx/bin/$(SHELL))
- $(DD Simple command line shell)
- )
+ $(LI Copy the standard library and runtime sources to $(D /usr/include/d/dmd):
- $(DT $(D $(DMDDIR)/osx/bin/$(DMD_CONF))
- $(DD Global compiler settings (copy to $(D /etc/dmd.conf)))
- )
+$(CONSOLE
+sudo mkdir -p /usr/include/d/dmd
+sudo cp $(DMDDIR)/{phobos/std,phobos/etc,druntime/import} /usr/include/d/dmd
+)
- $(DT $(D $(DMDDIR)/osx/lib/$(LIB))
- $(DD D runtime library (copy to $(D /usr/lib/$(LIB))))
- )
+ )
+ ))
)
- )
+ $(FREEBSD
-$(LNAME2 installation, Installation)
+ $(INSTALLATION_SCRIPT_HINT)
- $(WINDOWS
- $(P 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.
- $(D dmd.zip) will create
- a $(D $(DMDDIR)) directory with all the files in it.
- $(D dmc.zip) will create
- a $(D \dm) directory with all the files in it.
- )
-
- $(P A typical session might look like:)
+ $(P $(UL
-$(CONSOLE
-C:\Documents and Settings\Your Name>cd \
-C:\>unzip dmd.zip
-C:\>unzip dmc.zip
-)
- )
- $(LINUX
- $(LI Unzip the archive into your home directory.
- It will create
- a $(D ~/dmd) directory with all the files in it.
- All the tools are command line tools, which means
- they are run from a console window.)
+ $(LI Unzip the archive into your home directory.
+ It will create
+ a $(D ~/dmd) directory with all the files in it.
+ All the tools are command line tools, which means
+ they are run from a console window.)
- $(LI Copy $(D $(DMD_CONF)) to $(D /etc):
+ $(LI Create a configuration file in $(D /etc/dmd.conf):
-$(CONSOLE
-cp $(DMDDIR)/linux/bin/$(DMD_CONF) /etc
-)
- )
+---
+[Environment64]
+DFLAGS=-I/usr/local/include/d/dmd -L-L/usr/local/lib -L--export-dynamic -fPIC
+---
+
+ )
- $(LI Put $(D $(DMDDIR)/linux/bin) on your $(B PATH),
- or copy the linux executables
- to $(D /usr/local/bin))
- $(LI Copy the library to $(D /usr/lib):
+ $(LI Put $(D $(DMDDIR)/freebsd/bin) on your $(B PATH),
+ or copy the FreeBSD executables
+ to $(D /usr/local/bin):)
$(CONSOLE
-cp $(DMDDIR)/linux/lib/$(LIB) /usr/lib
+sudo cp $(DMDDIR)/linux/bin64/{dmd,$(DUMPOBJ),$(OBJ2ASM),rdmd,ddemangle,dub,dustmite} /usr/local/bin
)
- )
- )
- $(FREEBSD
- $(LI Unzip the archive into your home directory.
- It will create
- a $(D ~/dmd) directory with all the files in it.
- All the tools are command line tools, which means
- they are run from a console window.)
- $(LI Copy $(D $(DMD_CONF)) to $(D /etc):
+ $(LI Copy the library to $(D /usr/lib):
$(CONSOLE
-cp $(DMDDIR)/freebsd/bin/dmd.conf /etc
+sudo cp $(DMDDIR)/freebsd/lib/$(LIB) /usr/lib
)
- )
-
- $(LI Put $(D $(DMDDIR)/freebsd/bin) on your $(B PATH),
- or copy the FreeBSD executables
- to $(D /usr/local/bin))
+ )
- $(LI Copy the library to $(D /usr/lib):
+ $(LI Copy the standard library and runtime sources to $(D /usr/include/d/dmd):
$(CONSOLE
-cp $(DMDDIR)/freebsd/lib/$(LIB) /usr/lib
+sudo mkdir -p /usr/include/d/dmd
+sudo cp $(DMDDIR)/{phobos/std,phobos/etc,druntime/import} /usr/include/d/dmd
)
- )
+ )
+ ))
)
$(OSX
- $(LI Put the dmd zip file into your home directory,
- and unzip it:
+
+ $(INSTALLATION_SCRIPT_HINT)
+
+ $(P $(UL
+
+ $(LI Put the dmd zip file into your home directory,
+ and unzip it:
$(CONSOLE
unzip dmd.$(I VERSION).zip
)
- where $(I VERSION) is the particular version of the zip file.
- )
+ where $(I VERSION) is the particular version of the zip file.
+ )
- $(LI It will create
- a $(D ~/$(DMDDIR)) directory with all the files in it.
- All the tools are command line tools, which means
- they are run from a console window.)
+ $(LI It will create
+ a $(D ~/$(DMDDIR)) directory with all the files in it.
+ All the tools are command line tools, which means
+ they are run from a console window.)
- $(LI Verify that this works by creating $(D hello.d) in your home directory
- with these contents:
+ $(LI Verify that this works by creating $(D hello.d) in your home directory
+ with these contents:
---
import std.stdio;
-void main() {
+void main()
+{
writeln("hello world!");
}
---
- and compile and run it with:
+ and compile and run it with:
$(CONSOLE
$(DMDDIR)/osx/bin/dmd hello
./hello
)
- and it should print:
+ and it should print:
$(CONSOLE
hello world!
)
- )
+ )
- $(LI To install a global copy:)
+ $(LI To install a global copy:)
- $(LI Copy binaries to $(D /usr/local/bin):
+ $(LI Copy binaries to $(D /usr/local/bin):
$(CONSOLE
-sudo cp $(DMDDIR)/osx/bin/{dmd,$(DUMPOBJ),$(OBJ2ASM),$(SHELL)$(V2 ,rdmd)} /usr/local/bin
+sudo cp $(DMDDIR)/osx/bin/{dmd,$(DUMPOBJ),$(OBJ2ASM),rdmd,dub,ddemangle,dustmite} /usr/local/bin
sudo cp $(DMDDIR)/osx/bin/dmdx.conf /usr/local/bin/$(DMD_CONF)
)
- )
+ )
+
+ $(LI Copy the library to $(D /usr/local/lib):
+
+$(CONSOLE
+sudo cp $(DMDDIR)/osx/lib/$(LIB) /usr/local/lib
+)
+ )
- $(LI Copy the library to $(D /usr/lib):
+ $(LI Copy the standard library and runtime sources to $(D /usr/local/include/d/dmd):
$(CONSOLE
-sudo cp $(DMDDIR)/osx/lib/$(LIB) /usr/lib
+sudo mkdir -p /usr/include/d/dmd
+sudo cp $(DMDDIR)/{phobos/std,phobos/etc,druntime/import} /usr/include/d/dmd
)
- )
+ )
+
+ ))
)
$(WINDOWS
-$(LNAME2 example, Example)
+$(H2 $(H2 $(LNAME2 example, Example)))
- $(P Run:)
+ $(P Run:)
$(CONSOLE
$(DMDDIR)$(SEP)$(OS)$(SEP)bin$(SEP)$(SHELL) all.sh
)
- $(P in the $(D $(DMDDIR)$(SEP)samples$(SEP)d) directory for several small examples.)
-)
+ $(P in the $(D $(DMDDIR)$(SEP)samples$(SEP)d) directory for several small examples.)
+)
+
+
+$(H2 $(LNAME2 switches, Compiler Arguments and Switches))
+
+ $(DL
+ $(DT $(B dmd) $(I files)... -$(I switches)...
+ $(DD )
+ )
+
+ $(DT $(I files)...
+ $(DD
+ $(TABLE2 File Extensions,
+ $(TR
+ $(TH Extension)
+ $(TH File Type)
+ )
+ $(TR
+ $(TD $(I none))
+ $(TD D source files)
+ )
+ $(TR
+ $(TD $(B .c))
+ $(TD C source files)
+ )
+ $(TR
+ $(TD $(B .d))
+ $(TD D source files)
+ )
+ $(TR
+ $(TD $(B .dd))
+ $(TD $(LINK2 spec/ddoc.html, Ddoc) source files)
+ )
+ $(TR
+ $(TD $(B .di))
+ $(TD $(RELATIVE_LINK2 interface-files, D interface files))
+ )
+ $(TR
+ $(TD $(B .h))
+ $(TD C header files)
+ )
+ $(TR
+ $(TD $(B .i))
+ $(TD preprocessed C source files)
+ )
+ $(TR
+ $(TD $(B .$(OBJEXT)))
+ $(TD Object files to link in)
+ )
+ $(TR
+ $(TD $(B .$(LIBEXT)))
+ $(TD Object code libraries to search)
+ )
+$(WINDOWS
+ $(TR
+ $(TD $(B .exe))
+ $(TD Output executable file)
+ )
+ $(TR
+ $(TD $(B .def))
+ $(TD $(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, module definition file))
+ )
+ $(TR
+ $(TD $(B .res))
+ $(TD resource file)
+ )
+)
+ )
+ )
+ )
+
+ $(SWITCH $(B @)$(I cmdfile),
+ If $(I cmdfile) is an environment variable,
+ read the compiler arguments and switches from
+ the value of that variable.
+ Otherwise, read compiler arguments and switches from
+ the text file $(I cmdfile).
+ The file may contain single-line comments starting
+ with the hash symbol ($(CODE #)).
+ )
+
+ $(CLI_SWITCHES)
+ )
+ $(WINDOWS
+ $(P Empty switches, i.e. "", are ignored.)
+ )
-$(LNAME2 switches, Compiler Arguments and Switches)
-
- $(DL
- $(DT $(B dmd) $(I files)... -$(I switches)...
- $(DD )
- )
-
- $(DT $(I files)...
- $(DD
- $(TABLE2 File Extensions,
- $(TR
- $(TH Extension)
- $(TH File Type)
- )
- $(TR
- $(TD $(I none))
- $(TD D source files)
- )
- $(TR
- $(TD $(B .d))
- $(TD D source files)
- )
- $(TR
- $(TD $(B .dd))
- $(TD $(LINK2 ddoc.html, Ddoc) source files)
- )
- $(TR
- $(TD $(B .di))
- $(TD $(LINK2 #interface_files, D interface files))
- )
- $(TR
- $(TD $(B .$(OBJEXT)))
- $(TD Object files to link in)
- )
- $(TR
- $(TD $(B .$(LIBEXT)))
- $(TD Object code libraries to search)
- )
-$(WINDOWS
- $(TR
- $(TD $(B .exe))
- $(TD Output executable file)
- )
- $(TR
- $(TD $(B .def))
- $(TD $(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, module definition file))
- )
- $(TR
- $(TD $(B .res))
- $(TD resource file)
- )
-)
- )
- )
- )
-
- $(SWITCH $(B @)$(I cmdfile),
- If $(I cmdfile) is an environment variable,
- read the compiler arguments and switches from
- the value of that variable.
- Otherwise, read compiler arguments and switches from
- the text file $(I cmdfile)
- )
-
- $(SWITCH $(B -c),
- compile only, do not link
- )
-
- $(SWITCH $(B -cov),
- instrument for $(LINK2 code_coverage.html, code coverage analysis)
- )
-
- $(SWITCH $(B -D),
- generate $(LINK2 ddoc.html, documentation) from source
- )
-
- $(SWITCH $(B -Dd)$(I docdir),
- write documentation file to $(I docdir) directory
- )
-
- $(SWITCH $(B -Df)$(I filename),
- write documentation file to $(I filename)
- )
-
- $(SWITCH $(B -d),
- allow deprecated features
- )
- $(SWITCH $(B -debug),
- compile in $(LINK2 version.html#debug, debug) code
- )
- $(SWITCH $(B -debug=)$(I level),
- compile in $(LINK2 version.html#debug, debug level) <= $(I level)
- )
- $(SWITCH $(B -debug=)$(I ident),
- compile in $(LINK2 version.html#debug, debug identifier) $(I ident)
- )
-
- $(SWITCH $(B -debuglib=)$(I libname),
- link in $(I libname) as the default library when
- compiling for symbolic debugging instead of $(B $(LIB))
- )
- $(SWITCH $(B -defaultlib=)$(I libname),
- link in $(I libname) as the default library when
- not compiling for symbolic debugging instead of $(B $(LIB))
- )
- $(SWITCH $(B -deps=)$(I filename),
- write module dependencies as text to $(I filename)
- )
+$(H2 $(LNAME2 files, Files))
- $(UNIX
- $(SWITCH $(B -fPIC),
- generate Position Independent Code (which is used
- for building shared libraries).
- $(OSX This is always on for OSX.)
- )
+ $(DL
+
+ $(DT $(D $(DMDDIR)$(SEP)src$(SEP)phobos$(SEP))
+ $(DD D runtime library source)
)
- $(SWITCH $(B -g),
- $(WINDOWS
- add CodeView 4 symbolic debug info with
- $(LINK2 abi.html#codeview, D extensions)
- for debuggers such as
- $(LINK2 http://ddbg.mainia.de/releases.html, Ddbg)
+ $(DT $(D $(DMDDIR)$(SEP)src$(SEP)dmd$(SEP))
+ $(DD D compiler front end source under dual (GPL and Artistic) license)
)
- $(UNIX
- add Dwarf symbolic debug info with
- $(LINK2 abi.html#dwarf, D extensions)
- for debuggers $(LINUX such as
- $(LINK2 http://www.zerobugs.org/, ZeroBUGS))
+
+ $(DT $(D $(DMDDIR)$(SEP)html$(SEP)d$(SEP))
+ $(DD Documentation)
)
- )
- $(SWITCH $(B -gc),
+ $(DT $(D $(DMDDIR)$(SEP)samples$(SEP)d$(SEP))
+ $(DD Sample D programs)
+ )
$(WINDOWS
- add CodeView 4 symbolic debug info in C format
- for debuggers such as
- $(D $(DMDDIR)\bin\windbg)
+
+ $(DT $(D $(DMDDIR)\windows\bin\ddemangle.exe)
+ $(DD D symbol demangler)
)
- $(UNIX
- add Dwarf symbolic debug info in C format
- for debuggers such as
- $(D gdb)
- )
- )
-
- $(SWITCH $(B -gs),
- always generate standard stack frame
- )
-
- $(SWITCH $(B -H),
- generate $(LINK2 #interface_files, D interface file)
- )
-
- $(SWITCH $(B -Hd)$(I dir),
- write D interface file to $(I dir) directory
- )
-
- $(SWITCH $(B -Hf)$(I filename),
- write D interface file to $(I filename)
- )
-
- $(SWITCH $(B --help),
- print brief help to console
- )
-
- $(SWITCH $(B -I)$(I path),
- where to look for
- $(LINK2 module.html#ImportDeclaration, imports).
- $(I path) is a ; separated
- list of paths. Multiple $(B -I)'s can be used, and the paths
- are searched in the same order.
- )
-
- $(SWITCH $(B -ignore),
- ignore unsupported pragmas
- )
-
- $(SWITCH $(B -inline),
- inline expand functions at the discretion of the compiler.
- This can improve performance, at the expense of making
- it more difficult to use a debugger on it.
- )
-
- $(SWITCH $(B -J)$(I path),
- where to look for files for
- $(LINK2 expression.html#ImportExpression, $(I ImportExpression))s.
- This switch is required in order to use $(I ImportExpression)s.
- $(I path) is a ; separated
- list of paths. Multiple $(B -J)'s can be used, and the paths
- are searched in the same order.
- )
-
- $(SWITCH $(B -L)$(I linkerflag),
- pass $(I linkerflag) to the
- $(WINDOWS $(LINK2 http://www.digitalmars.com/ctg/optlink.html, linker))
- $(UNIX linker), for example,
- $(WINDOWS $(D -L/ma/li))$(UNIX $(D -L-M))
- )
-
- $(SWITCH $(B -lib),
- generate library file as output instead of object file(s).
- All compiled source files, as well as object files and library
- files specified on the command line, are inserted into
- the output library.
- Compiled source modules may be partitioned into several object
- modules to improve granularity.
- The name of the library is taken from the name of the first
- source module to be compiled. This can be overridden with
- the $(B -of) switch.
- )
- $(UNIX
- $(SWITCH $(B -m32),
- compile a 32 bit executable. This is the default for the
- 32 bit dmd.
- )
+ $(DT $(D $(DMDDIR)\windows\bin\dman.exe)
+ $(DD D manual lookup tool)
+ )
- $(SWITCH $(B -m64),
- compile a 64 bit executable. This is the default for the 64 bit dmd.
- )
+ $(DT $(D $(DMDDIR)\windows\bin\dmd.exe)
+ $(DD D compiler executable)
)
- $(SWITCH $(B -man),
- $(WINDOWS
- open default browser on this page
+ $(DT $(D $(DMDDIR)\windows\bin\$(DUB))
+ $(DD D's package manager)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\bin\$(DUSTMITE))
+ $(DD D source code minimizer)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\bin\$(OPTLINK))
+ $(DD OPTLINK)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\bin\$(LINK2 http://www.digitalmars.com/ctg/make.html, make.exe))
+ $(DD Digitalmars Make)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\bin\replace.exe)
+ $(DD Find/replace text in files)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\bin\$(RDMD))
+ $(DD D build tool for script-like D code execution)
+ )
+
+ $(DT $(D $(SC_INI))
+ $(DD Global compiler settings)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\bin\$(LINK2 http://www.digitalmars.com/ctg/shell.html, shell.exe))
+ $(DD Simple command line shell)
+ )
+
+ $(DT $(D $(DMDDIR)\windows\lib\$(LIB))
+ $(DD D runtime library)
+ )
)
$(LINUX
- open browser specified by the $(B BROWSER)
- environment variable on this page. If $(B BROWSER) is
- undefined, $(B x-www-browser) is assumed.
+ $(DT $(D $(DMDDIR)/linux/bin/ddemangle)
+ $(DD D symbol demangler)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/dman)
+ $(DD D manual lookup tool)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/dmd)
+ $(DD D compiler executable)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/$(DMD_CONF))
+ $(DD Global compiler settings (copy to $(D /etc/dmd.conf)))
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/$(DUB))
+ $(DD D's package manager)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/$(DUMPOBJ))
+ $(DD ELF file dumper)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/$(DUSTMITE))
+ $(DD D source code minimizer)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/$(OBJ2ASM))
+ $(DD ELF file disassembler)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/bin/$(RDMD))
+ $(DD D build tool for script-like D code execution)
+ )
+
+ $(DT $(D $(DMDDIR)/linux/lib/$(LIB))
+ $(DD D runtime library (copy to $(D /usr/lib/$(LIB))))
+ )
)
$(FREEBSD
- open browser specified by the $(B BROWSER)
- environment variable on this page. If $(B BROWSER) is
- undefined, $(B x-www-browser) is assumed.
+ $(DT $(D $(DMDDIR)/freesd/bin/ddemangle)
+ $(DD D symbol demangler)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/dman)
+ $(DD D manual lookup tool)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/dmd)
+ $(DD D compiler executable)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(DMD_CONF))
+ $(DD Global compiler settings (copy to $(D /etc/dmd.conf)))
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(DUB))
+ $(DD D's package manager)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(DUMPOBJ))
+ $(DD ELF file dumper)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(DUSTMITE))
+ $(DD D source code minimizer)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(OBJ2ASM))
+ $(DD ELF file disassembler)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(RDMD))
+ $(DD D build tool for script-like D code execution)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/bin/$(SHELL))
+ $(DD Simple command line shell)
+ )
+
+ $(DT $(D $(DMDDIR)/freebsd/lib/$(LIB))
+ $(DD D runtime library (copy to $(D /usr/lib/$(LIB))))
+ )
)
$(OSX
- open browser specified by the $(B BROWSER)
- environment variable on this page. If $(B BROWSER) is
- undefined, $(B Safari) is assumed.
+ $(DT $(D $(DMDDIR)/osx/bin/ddemangle)
+ $(DD D symbol demangler)
)
- )
- $(SWITCH $(B -map),
- generate a .map file
- )
+ $(DT $(D $(DMDDIR)/osx/bin/dman)
+ $(DD D manual lookup tool)
+ )
-$(V2
- $(SWITCH $(B -noboundscheck),
- turns off all array bounds checking, even for safe functions
- )
-)
- $(WINDOWS
- $(SWITCH $(B -nofloat),
- Prevents emission of $(B __fltused) reference in
- object files, even if floating point code is present.
- Useful for library code.
- )
- )
-
- $(SWITCH $(B -O),
- Optimize generated code. For fastest executables, compile
- with the $(B -O -release -inline) switches together.
- )
-
- $(SWITCH $(B -o-),
- Suppress generation of object file. Useful in
- conjuction with $(B -D) or $(B -H) flags.
- )
-
- $(SWITCH $(B -od)$(I objdir),
- $(DD write object files relative to directory $(I objdir)
- instead of to the current directory)
- )
- $(SWITCH $(B -of)$(I filename),
- Set output file name to $(I filename) in the output
- directory. The output file can be an object file,
- executable file, or library file depending on the other
- switches.
- )
- $(SWITCH $(B -op),
- normally the path for $(B .d) source files is stripped
- off when generating an object file name. $(B -op) will leave
- it on.
- )
- $(SWITCH $(B -profile),
- $(LINK2 http://www.digitalmars.com/ctg/trace.html, profile)
- the runtime performance
- of the generated code
- )
-$(V2
- $(SWITCH $(B -property),
- enforce use of @property on property functions
- )
-)
- $(SWITCH $(B -quiet),
- suppress non-essential compiler messages
- )
- $(SWITCH $(B -release),
- $(V1 compile release version, which means not generating
- code for contracts, asserts and array bounds checking)
- $(V2 compile release version, which means not generating
- code for contracts and asserts. Array bounds checking
- is not done for system and trusted functions.)
- )
- $(SWITCH $(B -run) $(I srcfile args...)
- compile, link, and run the program $(I srcfile) with the
- rest of the
- command line, $(I args...), as the arguments to the program.
- No .$(OBJEXT) or executable file is left behind.
- )
-$(COMMENT
- $(SWITCH $(B -safe),
- Statically checks the modules being compiled to ensure they
- conform to the $(LINK2 safed.html, safe memory model).
- )
-)
- $(UNIX
- $(SWITCH $(B -shared),
- generate shared library
- )
- )
- $(SWITCH $(B -unittest),
- compile in $(LINK2 unittest.html, unittest) code, turns on asserts, and sets the
- $(D unittest) $(LINK2 version.html#PredefinedVersions, version identifier)
- )
- $(SWITCH $(B -v),
- verbose
- )
- $(SWITCH $(B -version=)$(I level),
- compile in $(LINK2 version.html#version, version level) >= $(I level)
- )
- $(SWITCH $(B -version=)$(I ident),
- compile in $(LINK2 version.html#version, version identifier) $(I ident)
- )
-$(V2
- $(SWITCH $(B -vtls),
- print informational messages identifying variables defaulting
- to thread local storage. Handy for migrating to shared model.
- )
-)
- $(SWITCH $(B -w),
- enable $(LINK2 warnings.html, warnings)
- )
- $(SWITCH $(B -wi),
- enable $(LINK2 warnings.html, informational warnings (i.e. compilation
- still proceeds normally))
- )
- $(SWITCH $(B -X),
- generate JSON file
- )
- $(SWITCH $(B -Xf)$(I filename),
- write JSON file to $(I filename)
- )
- )
+ $(DT $(D $(DMDDIR)/osx/bin/dmd)
+ $(DD D compiler executable)
+ )
- $(WINDOWS
- $(P Empty switches, i.e. "", are ignored.)
+ $(DT $(D $(DMDDIR)/osx/bin/$(DMD_CONF))
+ $(DD Global compiler settings (copy to $(D /etc/dmd.conf)))
+ )
+
+ $(DT $(D $(DMDDIR)/osx/bin/$(DUB))
+ $(DD D's package manager)
+ )
+
+ $(DT $(D $(DMDDIR)/osx/bin/$(DUMPOBJ))
+ $(DD Mach-O file dumper)
)
-$(LNAME2 linking, Linking)
+ $(DT $(D $(DMDDIR)/osx/bin/$(DUSTMITE))
+ $(DD D source code minimizer)
+ )
- $(P Linking is done directly by the $(B dmd) compiler after a successful
- compile. To prevent $(B dmd) from running the linker, use the
- $(B -c) switch.
- )
+ $(DT $(D $(DMDDIR)/osx/bin/$(OBJ2ASM))
+ $(DD Mach-O file disassembler)
+ )
+
+ $(DT $(D $(DMDDIR)/osx/bin/$(RDMD))
+ $(DD D build tool for script-like D code execution)
+ )
+
+ $(DT $(D $(DMDDIR)/osx/bin/$(SHELL))
+ $(DD Simple command line shell)
+ )
+
+ $(DT $(D $(DMDDIR)/osx/lib/$(LIB))
+ $(DD D runtime library (copy to $(D /usr/local/lib/$(LIB))))
+ )
+ )
+
+ )
+
+
+
+$(H2 $(LNAME2 linking, Linking))
+
+ $(P Linking is done directly by the $(B dmd) compiler after a successful
+ compile. To prevent $(B dmd) from running the linker, use the
+ $(SWLINK -c) switch.
+ )
$(WINDOWS
- $(P The programs must be linked with the D runtime library $(B phobos.lib),
- followed by the C runtime library $(B 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:
- )
+ $(P 32 bit programs must be linked with the D runtime library $(B phobos.lib),
+ followed by the Digital Mars C runtime library $(B snn.lib).
+ This is done automatically as long as the directories for the
+ libraries are on the $(B LIB) environment variable path. A typical
+ way to set $(B LIB) would be:
+ )
$(CONSOLE
set LIB=$(DMDDIR)\lib;\dm\lib
)
- $(P If the $(B dmd) command is used to both compile and link
- to an executable, it will make certain optimizations that are
- valid only for Windows executable files. Do not use the resulting
- .obj files in a DLL.
- To compile modules into .obj files that can be used in an exe or
- DLL, compile with $(B -c).
- )
-
- $(P Linking is done using the
- $(LINK2 http://www.digitalmars.com/ctg/optlink.html, optlink) linker.
- )
+ $(P If the $(B dmd) command is used to both compile and link
+ to an executable, it will make certain optimizations that are
+ valid only for Windows executable files. Do not use the resulting
+ .obj files in a DLL.
+ To compile modules into .obj files that can be used in an exe or
+ DLL, compile with $(SWLINK -c) and $(SWLINK -shared).
+ )
+
+ $(P Linking 32 bit programs is done using Digital Mars $(OPTLINK).
+ )
+
+ $(P Linking 64 bit programs is done using the
+ Microsoft linker by default. If the Microsoft linker is not found,
+ the included LLVM linker LLD will be used.
+ )
)
$(UNIX
- $(P The actual linking is done by running $(B gcc).
- This ensures compatibility with modules compiled with $(B gcc).
- )
+ $(P The actual linking is done by running $(B gcc).
+ This ensures compatibility with modules compiled with $(B gcc).
+ )
)
-$(LNAME2 environment, Environment Variables)
+$(H2 $(LNAME2 environment, Environment Variables))
- $(P The D compiler dmd uses the following environment variables:
- )
+ $(P The D compiler dmd uses the following environment variables:
+ )
- $(DL
+ $(DL
$(WINDOWS
- $(LNAME2 sc_ini, sc.ini Initialization File)
+$(H2 $(LEGACY_LNAME2 sc_ini, sc-ini, sc.ini Initialization File)) - $(P $(B dmd) will look for the initialization file $(B sc.ini) in the - following sequence of directories: - ) + $(P $(B dmd) will look for the initialization file $(B sc.ini) in the + following sequence of directories: + ) - $(OL - $(LI current working directory) - $(LI directory specified by the $(B HOME) environment variable) - $(LI directory $(B dmd.exe) resides in) - ) + $(OL + $(LI current working directory) + $(LI directory specified by the $(B HOME) environment variable) + $(LI directory $(B dmd.exe) resides in) + ) - $(P If found, environment variable - settings in the file will override any existing settings. - This is handy to make $(B dmd) independent of programs with - conflicting use of environment variables. - ) + $(P If found, environment variable + settings in the file will override any existing settings. + This is handy to make $(B dmd) independent of programs with + conflicting use of environment variables. + ) -Initialization File Format
+$(H3 Initialization File Format) - $(P Comments are lines that begin with $(D ;) and are ignored. - ) + $(P Comments are lines that begin with $(D ;) and are ignored. + ) - $(P Environment variables follow the $(D [Environment]) section - heading, in $(I NAME)=$(I value) pairs. - The $(I NAME)s are treated as upper case. - Comments are lines that start with ;. - For example: - ) + $(P Environment variables follow the $(D [Environment]) section + heading, in $(I NAME)=$(I value) pairs. + The $(I NAME)s are treated as upper case. + Comments are lines that start with ;. + For example: + ) $(SCINI ; sc.ini file for dmd @@ -811,65 +702,66 @@ $(SCINI ; to this file. [Environment] LIB="%@P%\..\lib";\dm\lib -$(V1 DFLAGS="-I%@P%\..\src\phobos") -$(V2 DFLAGS="-I%@P%\..\src\phobos" "-I%@P%\..\src\druntime\import") + +DFLAGS="-I%@P%\..\src\phobos" "-I%@P%\..\src\druntime\import" LINKCMD="%@P%\..\..\dm\bin" DDOCFILE=mysettings.ddoc ) -Location Independence of sc.ini
+$(H3 Location Independence of sc.ini) - $(P The $(B %@P%) is replaced with the path to $(D sc.ini). - Thus, if the fully qualified file name $(D sc.ini) is - $(D c:$(DMDDIR)\bin\sc.ini), then $(B %@P%) will be replaced with - $(D c:$(DMDDIR)\bin), and the above $(D sc.ini) will be - interpreted as: - ) + $(P The $(B %@P%) is replaced with the path to $(D sc.ini). + Thus, if the fully qualified file name $(D sc.ini) is + $(D c:$(DMDDIR)\bin\sc.ini), then $(B %@P%) will be replaced with + $(D c:$(DMDDIR)\bin), and the above $(D sc.ini) will be + interpreted as: + ) $(SCINI [Environment] LIB="c:$(DMDDIR)\bin\..\lib";\dm\lib -$(V1 DFLAGS="-Ic:$(DMDDIR)\bin\..\src\phobos") -$(V2 DFLAGS="-Ic:$(DMDDIR)\bin\..\src\phobos" "-Ic:$(DMDDIR)\bin\..\src\druntime\import") + +DFLAGS="-Ic:$(DMDDIR)\bin\..\src\phobos" "-Ic:$(DMDDIR)\bin\..\src\druntime\import" LINKCMD="c:$(DMDDIR)\bin\..\..\dm\bin" DDOCFILE=mysettings.ddoc ) - $(P This enables your dmd setup to be moved around without having - to re-edit $(D sc.ini). - ) + $(P This enables your dmd setup to be moved around without having + to re-edit $(D sc.ini). + ) ) $(UNIX -$(LNAME2 dmd_conf, dmd.conf Initialization File)
- - $(P The dmd file $(D dmd.conf) is the same as $(D sc.ini) - for Windows, it's just that the file has a different name, - enabling a setup common to both Windows and this system to be created - without having to re-edit the file.) - - $(P $(B dmd) will look for the initialization file $(D dmd.conf) in the - following sequence of directories:) - - $(OL - $(LI current working directory) - $(LI directory specified by the $(B HOME) environment variable) - $(LI directory $(B dmd) resides in) - $(LI $(D /etc/)) - ) - - $(P If found, environment variable - settings in the file will override any existing settings. - This is handy to make $(B dmd) independent of programs with - conflicting use of environment variables. - ) - - $(P Environment variables follow the $(D [Environment]) section - heading, in $(I NAME)=$(I value) pairs. - The $(I NAME)s are treated as upper case. - Comments are lines that start with ;. - For example: - ) +$(H2 $(LEGACY_LNAME2 dmd_conf, dmd-conf, dmd.conf Initialization File)) + + $(P The dmd file $(D dmd.conf) is the same as $(D sc.ini) + for Windows, it's just that the file has a different name, + enabling a setup common to both Windows and this system to be created + without having to re-edit the file.) + + $(P $(B dmd) will look for the initialization file $(D dmd.conf) in the + following sequence of directories:) + + $(OL + $(LI current working directory) + $(LI directory specified by the $(B HOME) environment variable) + $(LI as dotfile $(D .dmd.conf) in the directory specified by the $(B HOME) environment variable) + $(LI directory $(B dmd) resides in) + $(LI $(D /etc/)) + ) + + $(P If found, environment variable + settings in the file will override any existing settings. + This is handy to make $(B dmd) independent of programs with + conflicting use of environment variables. + ) + + $(P Environment variables follow the $(D [Environment]) section + heading, in $(I NAME)=$(I value) pairs. + The $(I NAME)s are treated as upper case. + Comments are lines that start with ;. + For example: + ) $(SCINI ; dmd.conf file for dmd @@ -877,100 +769,101 @@ $(SCINI ; and inserted. The special name %@P% is replaced with the path ; to this file. [Environment] -$(V1 DFLAGS=-I%@P%/../src/phobos) -$(V2 DFLAGS=-I%@P%/../src/phobos -I%@P%/../src/druntime/import) + +DFLAGS=-I%@P%/../src/phobos -I%@P%/../src/druntime/import ) ) $(WINDOWS -$(LNAME2 problems, Common Installation Problems)
- - $(UL - $(LI Using Cygwin's $(B unzip) utility has been known to cause - strange problems. - ) - $(LI 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 $(B cmd.exe) before trying Cygwin's. - ) - $(LI Installing $(B dmd) and $(B dmc) into directory paths with spaces - in them causes problems. - ) - ) +$(H2 $(LNAME2 problems, Common Installation Problems)) + + $(UL + $(LI Using Cygwin's $(B unzip) utility has been known to cause + strange problems. + ) + $(LI 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 $(B cmd.exe) before trying Cygwin's. + ) + $(LI Installing $(B dmd) and $(B $(DMC)) into directory paths with spaces + in them causes problems. + ) + ) )-
$(LNAME2 differences, Differences between Windows and Linux versions)
+$(H2 $(LNAME2 differences, Differences between Windows and Linux versions)) - $(UL - $(LI String literals are read-only under Linux. - Attempting to write to them - will cause a segment violation.) - ) + $(UL + $(LI String literals are read-only under Linux. + Attempting to write to them + will cause a segment violation.) + )-
$(LNAME2 interface_files, D Interface Files)
- - $(P When an import declaration is processed in a D source file, - the compiler searches for the D source file corresponding to - the import, and processes that source file to extract the - information needed from it. Alternatively, the compiler can - instead look for a corresponding $(I D interface file). - A D interface file contains only what an import of the module - needs, rather than the whole implementation of that module. - ) - - $(P The advantages of using a D interface file for imports rather - than a D source file are: - ) - - $(UL - $(LI D interface files are often significantly smaller and much - faster to process than the corresponding D source file.) - $(LI They can be used to hide the source code, for example, - one can ship an object code library along with D interface files - rather than the complete source code.) - ) - - $(P D interface files can be created by the compiler from a - D source file by using the $(B -H) switch to the compiler. - D interface files have the $(B .di) file extension. - When the compiler resolves an import declaration, it first looks - for a $(B .di) D interface file, then it looks for a D source - file. - ) - - $(P D interface files bear some analogous similarities to C++ - header files. But they are not required in the way that C++ - header files are, and they are not part of the D language. - They are a feature of the compiler, and serve only as an optimization - of the build process. - ) - -$(LNAME2 executable, Building Executables)
- - $(P $(B dmd) can build an executable much faster if as many of the - source files as possible are put on the command line.) - - $(P Another advantage to putting multiple source files on the same - invocation of $(B dmd) is that $(B dmd) will be able to do some level - of cross-module optimizations, such as function inlining across modules. - ) - -$(LNAME2 library, Building Libraries)
- - $(P There are three ways to build a library. For example, - given $(D foo.d) and $(D bar.d) which are to be compiled, and existing - object file $(D bar.$(OBJEXT)) and existing library - $(D def.$(LIBEXT)) which are - all to be combined into a library $(D foo.$(LIBEXT)):) - - $(OL - $(LI Compile modules separately and then run the librarian on them: +$(H2 $(LEGACY_LNAME2 interface_files, interface-files, D Interface Files)) + + $(P When an import declaration is processed in a D source file, + the compiler searches for the D source file corresponding to + the import, and processes that source file to extract the + information needed from it. Alternatively, the compiler can + instead look for a corresponding $(I D interface file). + A D interface file contains only what an import of the module + needs, rather than the whole implementation of that module. + ) + + $(P The advantages of using a D interface file for imports rather + than a D source file are: + ) + + $(UL + $(LI D interface files are often significantly smaller and much + faster to process than the corresponding D source file.) + $(LI They can be used to hide the source code, for example, + one can ship an object code library along with D interface files + rather than the complete source code.) + ) + + $(P D interface files can be created by the compiler from a + D source file by using the $(SWLINK -H) switch to the compiler. + D interface files have the $(B .di) file extension. + When the compiler resolves an import declaration, it first looks + for a $(B .di) D interface file, then it looks for a D source + file. + ) + + $(P D interface files bear some analogous similarities to C++ + header files. But they are not required in the way that C++ + header files are, and they are not part of the D language. + They are a feature of the compiler, and serve only as an optimization + of the build process. + ) + +$(H2 $(LNAME2 executable, Building Executables)) + + $(P $(B dmd) can build an executable much faster if as many of the + source files as possible are put on the command line.) + + $(P Another advantage to putting multiple source files on the same + invocation of $(B dmd) is that $(B dmd) will be able to do some level + of cross-module optimizations, such as function inlining across modules. + ) + $(P The $(D -i) flag can be used to automatically compile imported modules) + +$(H2 $(LNAME2 library, Building Libraries)) + + $(P There are three ways to build a library. For example, + given $(D foo.d) and $(D bar.d) which are to be compiled, and existing + object file $(D abc.$(OBJEXT)) and existing library + $(D def.$(LIBEXT)) which are + all to be combined into a library $(D foo.$(LIBEXT)):) + + $(OL + $(LI Compile modules separately and then run the librarian on them: $(WINDOWS $(CONSOLE dmd -c foo.d dmd -c bar.d -$(LINK2 http://www.digitalmars.com/ctg/lib.html, lib) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib +$(LIB) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib del foo.obj bar.obj ) ) @@ -983,14 +876,14 @@ ar -r foo.a foo.o bar.o abc.o def.a rm foo.o bar.o ) ) - This option is typical when using a makefile to avoid compiling - modules that have already been compiled. - ) - $(LI Compile modules together and then run the librarian on them: + This option is typical when using a makefile to avoid compiling + modules that have already been compiled. + ) + $(LI Compile modules together and then run the librarian on them: $(WINDOWS $(CONSOLE dmd -c foo.d bar.d -$(LINK2 http://www.digitalmars.com/ctg/lib.html, lib) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib +$(LIB) -c -p32 foo.lib foo.obj bar.obj abc.obj def.lib del foo.obj bar.obj ) ) @@ -1002,23 +895,23 @@ ar -r foo.a foo.o bar.o abc.o def.a rm foo.o bar.o ) ) - ) - $(LI Use $(B dmd) to compile and build library in one operation: + ) + $(LI Use $(B dmd) to compile and build library in one operation: $(CONSOLE dmd -lib foo.d bar.d abc.$(OBJEXT) def.$(LIBEXT) ) - No object files are written to disk, it's all done in memory. - Using $(B -lib) also has the advantage that modules may be compiled - into multiple object files rather than exactly one per module. - This improves granularity of the library without having to break - up the modules. - ) - ) + No object files are written to disk, it's all done in memory. + Using $(SWLINK -lib) also has the advantage that modules may be compiled + into multiple object files rather than exactly one per module. + This improves granularity of the library without having to break + up the modules. + ) + ) -$(LNAME2 compiling_dmd, Compiling dmd)
+$(H2 $(LEGACY_LNAME2 compiling_dmd, compiling-dmd, Compiling dmd)) - $(P Complete source code is provided to build the compiler. - Follow these steps:) + $(P Complete source code is provided to build the compiler. + Follow these steps:) $(WINDOWS $(CONSOLE @@ -1029,54 +922,56 @@ make -f win32.mak $(UNIX $(CONSOLE cd ~/$(DMDDIR)/src/dmd -make -f $(OS).mak +make -f posix.mak ) ) -$(LNAME2 compiling_phobos, Compiling Phobos)
+$(H2 $(LEGACY_LNAME2 compiling_phobos, compiling-phobos, Compiling Phobos)) + + $(P Complete source code is provided to build Phobos, the D runtime library. + Follow these steps:) - $(P Complete source code is provided to build Phobos, the D runtime library. - Follow these steps:) -$(V1 -$(WINDOWS -$(CONSOLE -cd $(DMDDIR)\src\phobos -make -f win32.mak DMD=$(DMDDIR)\$(OS)\bin\dmd -) -) -$(UNIX -$(CONSOLE -cd ~/$(DMDDIR)/src/phobos -make -f $(OS).mak DMD=~/$(DMDDIR)/$(OS)/bin/dmd -) -) -) -$(V2 $(WINDOWS $(CONSOLE cd $(DMDDIR)\src\druntime -make -f win32.mak DMD=$(DMDDIR)\$(OS)\bin\dmd +make -f win32.mak cd ..\phobos -make -f win32.mak DMD=$(DMDDIR)\$(OS)\bin\dmd +make -f win32.mak ) ) $(UNIX $(CONSOLE -cd ~/$(DMDDIR)/src/druntime -make -f posix.mak DMD=~/$(DMDDIR)/$(OS)/bin/dmd cd ../phobos -make -f $(OS).mak DMD=~/$(DMDDIR)/$(OS)/bin/dmd -) +make -f posix.mak ) ) + ) Macros: - TITLE=DMD Compiler for $(WINDOWS Windows)$(LINUX Linux)$(OSX OSX)$(FREEBSD FreeBSD) - WIKI=DCompiler - LIB=$(WINDOWS phobos.lib)$(UNIX $(V1 libphobos.a)$(V2 libphobos2.a)) - DMD_CONF=$(LINK2 #dmd_conf, dmd.conf) - SWITCH=$(DT $1)$(DD $+) - CATEGORY_DOWNLOAD=$0 + TITLE=DMD Compiler for $(WINDOWS Windows)$(LINUX Linux)$(OSX OSX)$(FREEBSD FreeBSD) + BODYCLASS=std dcompiler + LIB=$(WINDOWS phobos.lib)$(UNIX libphobos2.a) + DMD_CONF=$(RELATIVE_LINK2 dmd-conf, dmd.conf) + SC_INI=$(RELATIVE_LINK2 sc-ini, $(DMDDIR)\windows\bin\sc.ini) + DMC=$(LINK2 http://www.digitalmars.com/ctg/sc.html, dmc) + OPTLINK=$(LINK2 http://www.digitalmars.com/ctg/optlink.html, optlink.exe) + DUB=$(LINK2 https://github.com/dlang/dub, dub$(BINEXT)) + RDMD=$(LINK2 $(ROOT_DIR)rdmd.html, rdmd$(BINEXT)) + DUSTMITE=$(LINK2 https://github.com/CyberShadow/DustMite, dustmite$(BINEXT)) + OBJ2ASM=$(HTTP digitalmars.com/ctg/obj2asm.html, obj2asm$(BINEXT)) + DUMPOBJ=$(HTTP digitalmars.com/ctg/dumpobj.html, dumpobj$(BINEXT)) + CLI_SWITCHES=$1 + SHELL=$(HTTP digitalmars.com/ctg/shell.html, shell) + SUBNAV=$(SUBNAV_CLI_REFERENCE) + INSTALLATION_SCRIPT_HINT= +$(P +$(MESSAGE_BOX gray, $(B Hint) - The official $(LINK2 $(ROOT_DIR)download.html, packages) +performs these steps automatically. +Alternatively, you can install DMD in your user directory with +the $(LINK2 $(ROOT_DIR)install.html, install script). +) +) + _ = diff --git a/dcompiler.html b/dcompiler.html deleted file mode 100644 index 59b47ecc96..0000000000 --- a/dcompiler.html +++ /dev/null @@ -1,9 +0,0 @@ - - - -Specification
- -$(P -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
- -$(P -Embedded documentation comments are processed in a series of phases: -) - -$(OL - $(LI Lexical - documentation comments are identified and attached - to tokens.) - $(LI Parsing - documentation comments are associated with - specific declarations and combined.) - $(LI Sections - each documentation comment is divided up into - a sequence of sections.) - $(LI Special sections are processed.) - $(LI Highlighting of non-special sections is done.) - $(LI All sections for the module are combined.) - $(LI Macro text substitution is performed to produce the final result.) -) - -Lexical
- -$(P -Embedded documentation comments are one of the following forms: -) - -$(OL - $(LI $(D_COMMENT /** ... */) The two *'s after the opening /) - $(LI $(D_COMMENT /++ ... +/) The two +'s after the opening /) - $(LI $(D_COMMENT ///) The three slashes) -) - -$(P 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 *****************/ ---------------------------- - -$(P -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
- -$(P -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 $(I 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. -) - -$(P -If a documentation comment for a declaration consists only of the -identifier $(D ditto) -then the documentation comment for the previous declaration at the same -declaration scope is applied to this declaration as well. -) - -$(P -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
- -$(P -The document comment is a series of $(I Section)s. -A $(I 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
- -$(P -The first section is the $(I 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 $(I Summary) section is optional. -) - -Description
- -$(P -The next unnamed section is the $(I Description). -It consists of all the paragraphs following the $(I Summary) until -a section name is encountered or the end of the comment. -) - -$(P -While the $(I Description) section is optional, -there cannot be a $(I Description) without a $(I Summary) section. -) - ------------------------------------- -/*********************************** - * Brief summary of what - * myfunc does, forming the summary section. - * - * First paragraph of synopsis description. - * - * Second paragraph of - * synopsis description. - */ - -void myfunc() { } ------------------------------------- - -$(P -Named sections follow the $(I Summary) and $(I Description) unnamed sections. -) - -Standard Sections
- -$(P -For consistency and predictability, there are several standard sections. -None of these are required to be present. -) - --
-
-
- $(B Authors:) -
- Lists the author(s) of the declaration. ------------------------------------- -/** - * Authors: Melvin D. Nerd, melvin@mailinator.com - */ ------------------------------------- - -
- $(B Bugs:) -
- Lists any known bugs. ------------------------------------- -/** - * Bugs: Doesn't work for negative values. - */ ------------------------------------- - -
- $(B Date:) -
- Specifies the date of the current revision. The date should be in a form - parseable by std.date. - ------------------------------------- -/** - * Date: March 14, 2003 - */ ------------------------------------- - -
- $(B 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() { ... } ------------------------------------- - -
- $(B Examples:) -
- Any usage examples ------------------------------------- -/** - * Examples: - * -------------------- - * writefln("3"); // writes '3' to stdout - * -------------------- - */ ------------------------------------- - -
- $(B History:) -
- Revision history. ------------------------------------- -/** - * History: - * V1 is initial version - * - * V2 added feature X - */ ------------------------------------- - -
- $(B License:) -
- Any license information for copyrighted code. ------------------------------------- -/** - * License: use freely for any purpose - */ - -void bar() { ... } ------------------------------------- - -
- $(B Returns:) -
- Explains the return value of the function. - If the function returns $(B void), don't redundantly document it. ------------------------------------- -/** - * Read the file. - * Returns: The contents of the file. - */ - -void[] readFile(char[] filename) { ... } ------------------------------------- - -
- $(B See_Also:) -
- List of other symbols and URL's to related items. ------------------------------------- -/** - * See_Also: - * foo, bar, http://www.digitalmars.com/d/phobos/index.html - */ ------------------------------------- - -
- $(B Standards:) -
- If this declaration is compliant with any particular standard, -the description of it goes here. ------------------------------------- -/** - * Standards: Conforms to DSPEC-1234 - */ ------------------------------------- - -
- $(B Throws:) -
- Lists exceptions thrown and under what circumstances they are thrown. ------------------------------------- -/** - * Write the file. - * Throws: WriteException on failure. - */ - -void writeFile(char[] filename) { ... } ------------------------------------- - -
- $(B Version:) -
- Specifies the current version of the declaration. ------------------------------------- -/** - * Version: 1.6a - */ ------------------------------------- -
Special Sections
- -$(P -Some sections have specialized meanings and syntax. -) - --
-
-
- $(B 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; ------------------------------------- - -
- $(B 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) -{ -} -------------------------- - -
- $(B Macros:) -
- The macros section follows the same syntax as the $(B Params:) section. - It's a series of $(I NAME)=$(I value) pairs. - The $(I NAME) is the macro name, and $(I 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
- -$(P - The documentation comments can themselves be commented using - the $(DDOC_COMMENT comment text) syntax. These comments do not - nest. -) - -Embedded Code
- -$(P - D code can be embedded using lines beginning with at least three - hyphens (ignoring whitespace) to delineate the code section: -) - ------------------------------------- -/++ - + Our function. - + - + Example: - + --- - + import std.stdio; - + - + void foo() - + { - + writefln("foo!"); /* print the string */ - + } - + --- - +/ ------------------------------------- - -$(P - Note that the documentation comment uses the $(D_COMMENT /++ ... +/) - form - so that $(D_COMMENT /* ... */) can be used inside the code section. -) - -Embedded HTML
- -$(P -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: - * - *-
- *
- Digital Mars - *
- Empire - *
Emphasis
- -$(P -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
- -$(P - Some characters have special meaning - to the documentation processor, to avoid confusion it can be best - to replace them with their corresponding character entities: -) - - $(TABLE2 Characters and Entities, - $(TR $(TH Character) $(TH Entity)) - $(TR $(TD < )$(TD < )) - $(TR $(TD > )$(TD > )) - $(TR $(TD & )$(TD & )) - ) - -$(P - 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. -) - -No Documentation
- -$(P - No documentation is generated for the following constructs, - even if they have a documentation comment: -) - - $(UL - $(LI Invariants) -$(V2 $(LI Postblits)) - $(LI Destructors) - $(LI Static constructors and static destructors) - $(LI Class info, type info, and module info) - ) - -Macros
- -$(P - The documentation comment processor includes a simple macro - text preprocessor. - When a $($(I NAME)) appears - in section text it is replaced with $(I NAME)'s corresponding - replacement 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 $. -) - -$(P - Macros can have arguments. Any text from the end of the identifier - to the closing $(SINGLEQUOTE $(RPAREN)) 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 $(SINGLEQUOTE $(RPAREN)). - 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 ( for ( and ) for ). -) - -$(P - Macro definitions come from the following sources, - in the specified order: -) - - $(OL - $(LI Predefined macros.) - $(LI Definitions from file specified by $(DPLLINK dmd-windows.html#sc_ini, sc.ini)'s - or $(DPLLINK dmd-linux.html#dmd_conf, dmd.conf) DDOCFILE setting.) - $(LI Definitions from *.ddoc files specified on the command line.) - $(LI Runtime definitions generated by Ddoc.) - $(LI Definitions from any Macros: sections.) - ) - -$(P - Macro redefinitions replace previous definitions of the same name. - This means that the sequence of macro definitions from the various - sources forms a hierarchy. -) - -$(P - Macro names beginning with "D_" and "DDOC_" are reserved. -) - -Predefined Macros
- -$(P - 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. -) - -$(DDOCCODE -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="https://github.com/$0">$0</a> -LINK2 = <a href="https://github.com/$1">$+</a> -LPAREN= $(LPAREN) -RPAREN= $(RPAREN) - -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_COMMENT = <!-- $0 --> -DDOC_DECL = $(DT $(BIG $0)) -DDOC_DECL_DD = $(DD $0) -DDOC_DITTO = $(BR)$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_MODULE_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_CLASS_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_STRUCT_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_ENUM_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0) -DDOC_PARAMS = $(B Params:)$(BR)\n$(TABLE $0)$(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) -) - -$(P - 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. -) - - $(TABLE2 Basic Formatting Macros, - $(TR $(TD $(B B)) $(TD boldface the argument)) - $(TR $(TD $(B I)) $(TD italicize the argument)) - $(TR $(TD $(B U)) $(TD underline the argument)) - $(TR $(TD $(B P)) $(TD argument is a paragraph)) - $(TR $(TD $(B DL)) $(TD argument is a definition list)) - $(TR $(TD $(B DT)) $(TD argument is a definition in a definition list)) - $(TR $(TD $(B DD)) $(TD argument is a description of a definition)) - $(TR $(TD $(B TABLE)) $(TD argument is a table)) - $(TR $(TD $(B TR)) $(TD argument is a row in a table)) - $(TR $(TD $(B TH)) $(TD argument is a header entry in a row)) - $(TR $(TD $(B TD)) $(TD argument is a data entry in a row)) - $(TR $(TD $(B OL)) $(TD argument is an ordered list)) - $(TR $(TD $(B UL)) $(TD argument is an unordered list)) - $(TR $(TD $(B LI)) $(TD argument is an item in a list)) - $(TR $(TD $(B BIG)) $(TD argument is one font size bigger)) - $(TR $(TD $(B SMALL)) $(TD argument is one font size smaller)) - $(TR $(TD $(B BR)) $(TD start new line)) - $(TR $(TD $(B LINK)) $(TD generate clickable link on argument)) - $(TR $(TD $(B LINK2)) $(TD generate clickable link, first arg is address)) - $(TR $(TD $(B RED)) $(TD argument is set to be red)) - $(TR $(TD $(B BLUE)) $(TD argument is set to be blue)) - $(TR $(TD $(B GREEN)) $(TD argument is set to be green)) - $(TR $(TD $(B YELLOW)) $(TD argument is set to be yellow)) - $(TR $(TD $(B BLACK)) $(TD argument is set to be black)) - $(TR $(TD $(B WHITE)) $(TD argument is set to be white)) - $(TR $(TD $(B D_CODE)) $(TD argument is D code)) - $(TR $(TD $(B DDOC)) $(TD overall template for output)) - ) - -$(P - $(B DDOC) is special in that it specifies the boilerplate into - which the entire generated text is inserted (represented by the - Ddoc generated macro $(B BODY)). For example, in order - to use a style sheet, $(B DDOC) would be redefined as: -) - -$(DDOCCODE -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="https://github.com/$(B%20style.css)"> - </head><body> - <h1>$(TITLE)</h1> - $(BODY) - </body></html> -) - -$(P - $(B DDOC_COMMENT) is used to insert comments into the output - file. -) - -$(P - Highlighting of D code is performed by the following macros: -) - - $(TABLE2 D Code Formatting Macros, - $(TR $(TD $(B D_COMMENT)) $(TD Highlighting of comments)) - $(TR $(TD $(B D_STRING)) $(TD Highlighting of string literals)) - $(TR $(TD $(B D_KEYWORD)) $(TD Highlighting of D keywords)) - $(TR $(TD $(B D_PSYMBOL)) $(TD Highlighting of current declaration name)) - $(TR $(TD $(B D_PARAM)) $(TD Highlighting of current function declaration parameters)) - ) - -$(P - The highlighting macros start with $(B DDOC_). - They control the formatting of individual parts of the presentation. -) - - $(TABLE2 Ddoc Section Formatting Macros, - $(TR $(TD $(B DDOC_DECL)) $(TD Highlighting of the declaration.)) - $(TR $(TD $(B DDOC_DECL_DD)) $(TD Highlighting of the description of a declaration.)) - $(TR $(TD $(B DDOC_DITTO)) $(TD Highlighting of ditto declarations.)) - $(TR $(TD $(B DDOC_SECTIONS)) $(TD Highlighting of all the sections.)) - $(TR $(TD $(B DDOC_SUMMARY)) $(TD Highlighting of the summary section.)) - $(TR $(TD $(B DDOC_DESCRIPTION)) $(TD Highlighting of the description section.)) - $(TR $(TD $(B DDOC_AUTHORS .. DDOC_VERSION)) $(TD Highlighting of the corresponding standard section.)) - $(TR $(TD $(B DDOC_SECTION_H)) $(TD Highlighting of the section name of a non-standard section.)) - $(TR $(TD $(B DDOC_SECTION)) $(TD Highlighting of the contents of a non-standard section.)) - $(TR $(TD $(B DDOC_MEMBERS)) $(TD Default highlighting of all the members of a class, struct, etc.)) - $(TR $(TD $(B DDOC_MODULE_MEMBERS)) $(TD Highlighting of all the members of a module.)) - $(TR $(TD $(B DDOC_CLASS_MEMBERS)) $(TD Highlighting of all the members of a class.)) - $(TR $(TD $(B DDOC_STRUCT_MEMBERS)) $(TD Highlighting of all the members of a struct.)) - $(TR $(TD $(B DDOC_ENUM_MEMBERS)) $(TD Highlighting of all the members of an enum.)) - $(TR $(TD $(B DDOC_TEMPLATE_MEMBERS)) $(TD Highlighting of all the members of a template.)) - $(TR $(TD $(B DDOC_PARAMS)) $(TD Highlighting of a function parameter section.)) - $(TR $(TD $(B DDOC_PARAM_ROW)) $(TD Highlighting of a name=value function parameter.)) - $(TR $(TD $(B DDOC_PARAM_ID)) $(TD Highlighting of the parameter name.)) - $(TR $(TD $(B DDOC_PARAM_DESC)) $(TD Highlighting of the parameter value.)) - $(TR $(TD $(B DDOC_PSYMBOL)) $(TD Highlighting of declaration name to which a particular section is referring.)) - $(TR $(TD $(B DDOC_KEYWORD)) $(TD Highlighting of D keywords.)) - $(TR $(TD $(B DDOC_PARAM)) $(TD Highlighting of function parameters.)) - $(TR $(TD $(B DDOC_BLANKLINE)) $(TD Inserts a blank line.)) - ) - -$(P - For example, one could redefine $(B DDOC_SUMMARY): -) - -$(DDOCCODE -DDOC_SUMMARY = $(GREEN $0) -) - -$(P - And all the summary sections will now be green. -) - -Macro Definitions from $(DPLLINK dmd-windows.html#sc_ini, $(D sc.ini))'s DDOCFILE
- -$(P - A text file of macro definitions can be created, - and specified in $(D sc.ini): -) - -$(DDOCCODE -DDOCFILE=myproject.ddoc -) - -Macro Definitions from .ddoc Files on the Command Line
- -$(P - 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
- - $(TABLE2 Generated Macro Definitions, - $(TR - $(TH Macro Name) - $(TH Contents) - ) - $(TR - $(TD $(B BODY)) - $(TD Set to the generated document text.) - ) - $(TR - $(TD $(B TITLE)) - $(TD Set to the module name.) - ) - $(TR - $(TD $(B DATETIME)) - $(TD Set to the current date and time.) - ) - $(TR - $(TD $(B YEAR)) - $(TD Set to the current year.) - ) - $(TR - $(TD $(B COPYRIGHT)) - $(TD Set to the contents of any $(B Copyright:) section that is part - of the module comment.) - ) - $(TR - $(TD $(B DOCFILENAME)) - $(TD Set to the name of the generated output file.) - ) - ) - -Using Ddoc for other Documentation
- -$(P - Ddoc is primarily 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. -) - -$(P - 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. -) - -$(P - 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. -) - -References
- -$(P - $(LINK2 http://www.dsource.org/projects/helix/wiki/CandyDoc, CandyDoc) - is a very nice example of how - one can customize the Ddoc results with macros - and style sheets. -) - -) - -Macros: - TITLE=Documentation Generator - WIKI=Ddoc - CATEGORY_SPEC=$0 - RPAREN=) diff --git a/ddoc/.gitignore b/ddoc/.gitignore new file mode 100644 index 0000000000..646b0fa1e8 --- /dev/null +++ b/ddoc/.gitignore @@ -0,0 +1,4 @@ +/libddoc_preprocessor.a +/ddoc_preprocessor +/ddoc_preprocessor-test-application +/ddoc_preprocessor-test-library diff --git a/ddoc/dub.sdl b/ddoc/dub.sdl new file mode 100644 index 0000000000..6fce22a829 --- /dev/null +++ b/ddoc/dub.sdl @@ -0,0 +1,14 @@ +name "ddoc_preprocessor" +description "Preprocesses source code before running Ddoc over it" +dependency "libdparse" version="~>0.15.1" +# we only need an isolated single module from DMD +sourceFiles "../../dmd/compiler/src/dmd/cli.d" +importPaths "source" "../../dmd/compiler/src" +versions "DdocOptions" # for dmd.cli +buildRequirements "disallowDeprecations" +configuration "executable" { + versions "IsExecutable" + targetType "executable" +} +configuration "library" { +} diff --git a/ddoc/dub.selections.json b/ddoc/dub.selections.json new file mode 100644 index 0000000000..0d6de82c2c --- /dev/null +++ b/ddoc/dub.selections.json @@ -0,0 +1,7 @@ +{ + "fileVersion": 1, + "versions": { + "libdparse": "0.15.4", + "stdx-allocator": "2.77.5" + } +} diff --git a/ddoc/source/assert_writeln_magic.d b/ddoc/source/assert_writeln_magic.d new file mode 100755 index 0000000000..353c5d24cf --- /dev/null +++ b/ddoc/source/assert_writeln_magic.d @@ -0,0 +1,325 @@ +#!/usr/bin/env dub +/++ dub.sdl: +dependency "libdparse" version="~>0.24.0" +name "assert_writeln_magic" ++/ +/* + * Tries to convert `assert`s into user-friendly `writeln` calls. + * The objective of this tool is to be conservative as + * broken example look a lot worse than a few statements + * that could have potentially been rewritten. + * + * - only EqualExpressions are "lowered" + * - static asserts are ignored + * - only single-line assers are rewritten + * + * Copyright (C) 2017 by D Language Foundation + * + * Author: Sebastian Wilzbach + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) +*/ +// Written in the D programming language. + +import dparse.ast; +import std.algorithm; +import std.conv; +import std.experimental.logger; +import std.range; +import std.stdio; +import std.typecons; + +private string formatNode(T)(const T t) +{ + import dparse.formatter; + import std.array : appender; + + auto writer = appender!string(); + auto formatter = new Formatter!(typeof(writer))(writer); + formatter.format(t); + return writer.data; +} + +class TestVisitor(Out) : ASTVisitor +{ + import dparse.lexer : tok, Token; + + this(Out fl) + { + this.fl = fl; + } + + alias visit = ASTVisitor.visit; + + override void visit(const Unittest test) + { + resetTestState(); + inTest = true; + scope(exit) inTest = false; + test.accept(this); + + processLastAssert(); + } + + override void visit(const EqualExpression expr) + { + enum eqToken = tok!"=="; + if (inAssert && expr.operator == eqToken && expr.left !is null && expr.right !is null) + lastEqualExpression = expr; + } + + override void visit(const AssertExpression expr) + { + if (inFunctionCall) + return; + + // only look at `a == b` within the AssertExpression + if (!expr.assertArguments || + typeid(expr.assertArguments.assertion) != typeid(CmpExpression)) + return; + + lastAssert = expr; + inAssert = true; + expr.accept(this); + inAssert = false; + fromAssert = true; + } + + // for now static asserts are ignored + override void visit(const StaticAssertStatement expr) + { + fromStaticAssert = true; + expr.accept(this); + } + + /** + The following code (in std.concurrency) leads to false positives: + + assertNotThrown!AssertError(assert(receiveOnly!int() == i)); + + Hence we simply ignore all asserts in function calls. + */ + override void visit(const FunctionCallExpression expr) + { + inFunctionCall = true; + expr.accept(this); + inFunctionCall = false; + } + + /// A single line + override void visit(const DeclarationOrStatement expr) + { + processLastAssert(); + expr.accept(this); + } + + void processLastAssert() + { + import std.uni : isWhite; + import std.format : format; + + if (fromAssert && !fromStaticAssert && + lastEqualExpression !is null && lastAssert !is null) + { + auto e = lastEqualExpression; + if (e.left !is null && e.right !is null) + { + // libdparse starts the line count with 1 + auto lineNr = lastAssert.line - 1; + + // only replace single-line expressions (for now) + if (fl[lineNr].endsWith(";")) + { + auto wsLen = fl[lineNr].countUntil!(u => !u.isWhite); + auto indent = fl[lineNr][0 .. wsLen]; + + if (fl[lineNr][wsLen .. $].startsWith("assert", "static assert")) + { + auto left = lastEqualExpression.left.formatNode; + auto right = lastEqualExpression.right.formatNode; + + if (left.length + right.length > 80) + fl[lineNr] = format("%s// %s\n%swriteln(%s);", indent, right, indent, left); + else + fl[lineNr] = format("%swriteln(%s); // %s", indent, left, right); + + //writefln("line: %d, column: %d", lastAssert.line, lastAssert.column); + } + } + } + } + resetTestState(); + } + +private: + + void resetTestState() + { + fromAssert = false; + fromStaticAssert = false; + lastEqualExpression = null; + lastAssert = null; + } + + /// within in the node + bool inTest; + bool inAssert; + bool inFunctionCall; + + /// at a sibling after the node was seen, but the upper parent hasn't been reached yet + bool fromAssert; + bool fromStaticAssert; + + Rebindable!(const AssertExpression) lastAssert; + Rebindable!(const EqualExpression) lastEqualExpression; + + Out fl; +} + +void parseString(Visitor)(const string filepath, ubyte[] sourceCode, Visitor visitor) +{ + import dparse.lexer; + import dparse.parser : parseModule, ParserConfig; + import dparse.rollback_allocator : RollbackAllocator; + + LexerConfig config; + auto cache = StringCache(StringCache.defaultBucketCount); + const(Token)[] tokens = getTokensForParser(sourceCode, config, &cache).array; + + RollbackAllocator rba; + auto m = parseModule(ParserConfig(tokens, filepath, &rba)); + visitor.visit(m); +} + +private auto assertWritelnModuleImpl(const string filepath, string fileText) +{ + import std.string : representation; + auto fl = FileLines(fileText); + scope visitor = new TestVisitor!(typeof(fl))(fl); + // libdparse doesn't allow to work on immutable source code + parseString(filepath, cast(ubyte[]) fileText.representation, visitor); + return fl; +} + +auto assertWritelnModule(const string filepath, string fileText) +{ + return assertWritelnModuleImpl(filepath, fileText).buildLines; +} +auto assertWritelnBlock(const string filepath, string fileText) +{ + auto source = "unittest{\n" ~ fileText ~ "}\n"; + auto fl = assertWritelnModuleImpl(filepath, source); + auto app = appender!string; + foreach (line; fl.lines[1 .. $ - 2]) + { + app ~= line; + app ~= "\n"; + } + return app.data; +} + +/** +A simple line-based in-memory representation of a file. + - will automatically write all changes when the object is destructed + - will use a temporary file to do safe, whole file swaps +*/ +struct FileLines +{ + import std.array, std.file, std.path; + + string[] lines; + string destFile; + bool hasWrittenChanges; + + this(string inputText) + { + lines = inputText.split("\n"); + } + + // writes all changes to a random, temporary file + auto buildLines() { + auto app = appender!string; + // dump file + foreach (line; lines) + { + app ~= line; + app ~= "\n"; + } + // within the docs we automatically inject std.stdio (hence we need to do the same here) + // writeln needs to be @nogc, @safe, pure and nothrow (we just fake it) + app ~= "// \nprivate void writeln(T)(T l) { }"; + return app.data; + } + + string opIndex(size_t i) { return lines[i]; } + void opIndexAssign(string line, size_t i) { + hasWrittenChanges = true; + lines[i] = line; + } +} + +version(unittest) +{ + struct FileLinesMock + { + string[] lines; + string opIndex(size_t i) { return lines[i]; } + void opIndexAssign(string line, size_t i) { + lines[i] = line; + } + } + auto runTest(string sourceCode) + { + import std.string : representation; + auto mock = FileLinesMock(sourceCode.split("\n")); + scope visitor = new TestVisitor!(typeof(mock))(mock); + parseString("unittest.d", sourceCode.representation.dup, visitor); + return mock; + } +} + + +unittest +{ + "Running tests for assert_writeln_magic".writeln; + + // purposefully not indented + string testCode = q{ +unittest +{ +assert(equal(splitter!(a => a == ' ')("hello world"), [ "hello", "", "world" ])); +assert(equal(splitter!(a => a == 0)(a), w)); +} + }; + auto res = runTest(testCode); + assert(res.lines[3 .. $ - 2] == [ + "assert(equal(splitter!(a => a == ' ')(\"hello world\"), [ \"hello\", \"\", \"world\" ]));", + "assert(equal(splitter!(a => a == 0)(a), w));" + ]); +} + +unittest +{ + string testCode = q{ +unittest +{ +assert(1 == 2); +assert(foo() == "bar"); +assert(foo() == bar); +assert(arr == [0, 1, 2]); +assert(r.back == 1); +} + }; + auto res = runTest(testCode); + assert(res.lines[3 .. $ - 2] == [ + "writeln(1); // 2", + "writeln(foo()); // \"bar\"", + "writeln(foo()); // bar", + "writeln(arr); // [0, 1, 2]", + "writeln(r.back); // 1", + ]); + + "Successfully ran tests for assert_writeln_magic".writeln; +} diff --git a/ddoc/source/preprocessor.d b/ddoc/source/preprocessor.d new file mode 100644 index 0000000000..2ca4262cb4 --- /dev/null +++ b/ddoc/source/preprocessor.d @@ -0,0 +1,505 @@ +#!/usr/bin/env rdmd +/** +A wrapper around DDoc to allow custom extensions + +Copyright: D Language Foundation 2018 + +License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). + +Example usage: + +--- +./ddoc --compiler=Declaration Syntax
- -$(P Declaration syntax generally reads right to left:) - --------------------- -int x; // x is an int -int* x; // x is a pointer to int -int** x; // x is a pointer to a pointer to int -int[] x; // x is an array of ints -int*[] x; // x is an array of pointers to ints -int[]* x; // x is a pointer to an array of ints --------------------- - -$(P Arrays read right to left as well:) - --------------------- -int[3] x; // x is an array of 3 ints -int[3][5] x; // x is an array of 5 arrays of 3 ints -int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 ints --------------------- - -$(P -Pointers to functions are declared using the $(B function) keyword: -) - --------------------- -int $(B function)(char) x; // x is a pointer to - // a function taking a char argument - // and returning an int -int $(B function)(char)[] x; // x is an array of - // pointers to functions - // taking a char argument - // and returning an int --------------------- - -$(P -$(V1 C-style array, function pointer and pointer to array declarations are possible as an alternative:) -$(V2 C-style array, function pointer and pointer to array declarations are deprecated:) -) - --------------------- -int x[3]; // x is an array of 3 ints -int x[3][5]; // x is an array of 3 arrays of 5 ints -int (*x[5])[3]; // x is an array of 5 pointers to arrays of 3 ints -int (*x)(char); // x is a pointer to a function taking a char argument - // and returning an int -int (*[] x)(char); // x is an array of pointers to functions - // taking a char argument and returning an int --------------------- - -$(P -In a declaration declaring multiple symbols, all the declarations -must be of the same type: -) - --------------------- -int x,y; // x and y are ints -int* x,y; // x and y are pointers to ints -int x,*y; // error, multiple types -int[] x,y; // x and y are arrays of ints -int x[],y; // error, multiple types --------------------- - -Implicit Type Inference
- -$(GRAMMAR -$(GNAME AutoDeclaration): - $(GLINK StorageClasses) $(I AutoDeclarationX) $(B ;) - -$(GNAME AutoDeclarationX): - $(I Identifier) $(B =) $(GLINK Initializer) - $(I AutoDeclarationX) $(B ,) $(I Identifier) $(B =) $(GLINK Initializer) -) - - $(P If a declaration starts with a $(I StorageClass) and has - a $(I NonVoidInitializer) from which the type can be inferred, - the type on the declaration can be omitted. - ) - ----------- -static x = 3; // x is type int -auto y = 4u; // y is type uint -$(V1 auto s = "string"; // s is type char[6]) -$(V2 auto s = "string"; // s is type immutable(char)[]) - -class C { ... } - -auto c = new C(); // c is a handle to an instance of class C ----------- - - $(P The $(I NonVoidInitializer) cannot contain forward references - (this restriction may be removed in the future). - The implicitly inferred type is statically bound - to the declaration at compile time, not run time. - ) - -$(V2 - $(P An $(GLINK2 expression, ArrayLiteral) - is inferred to be a dynamic array - type rather than a static array:) - ---- -auto v = ["hello", "world"]; // type is string[], not string[2] ---- -) - -$(V1 -Type Defining
- - $(P - Strong types can be introduced with the typedef. Strong types are semantically a - distinct type to the type checking system, for function overloading, and for the debugger. - ) - --------------------- -typedef int myint; - -void foo(int x) { . } -void foo(myint m) { . } - - . -myint b; -foo(b); // calls foo(myint) --------------------- - -Typedefs can specify a default initializer different from the -default initializer of the underlying type: - --------------------- -typedef int myint = 7; -myint m; // initialized to 7 --------------------- -) - -Type Aliasing
- - $(P - $(GLINK AliasDeclaration)s create a symbol that is an alias for another type, - and can be used anywhere that other type may appear. - ) - --------------------- -$(B alias) abc.Foo.bar myint; --------------------- - - $(P - Aliased types are semantically identical to the types they are aliased to. The - debugger cannot distinguish between them, and there is no difference as far as function - overloading is concerned. For example: - ) - --------------------- -$(B alias) int myint; - -void foo(int x) { . } -void foo(myint m) { . } // error, multiply defined function foo --------------------- - -$(V1 - $(P - Type aliases are equivalent to the C typedef. - ) -) - -Alias Declarations
- - $(P - A symbol can be declared as an $(I alias) of another symbol. - For example: - ) - --------------------- -import string; - -$(B alias) string.strlen mylen; - ... -int len = mylen("hello"); // actually calls string.strlen() --------------------- - - $(P - The following alias declarations are valid: - ) - --------------------- -template Foo2(T) { $(B alias) T t; } -$(B alias) Foo2!(int) t1; -$(B alias) Foo2!(int).t t2; -$(B alias) t1.t t3; -$(B alias) t2 t4; - -t1.t v1; // v1 is type int -t2 v2; // v2 is type int -t3 v3; // v3 is type int -t4 v4; // v4 is type int --------------------- - - $(P - Aliased symbols are useful as a shorthand for a long qualified - symbol name, or as a way to redirect references from one symbol - to another: - ) - --------------------- -version (Win32) -{ - $(B alias) win32.foo myfoo; -} -version (linux) -{ - $(B alias) linux.bar myfoo; -} --------------------- - - $(P - Aliasing can be used to $(SINGLEQUOTE import) a symbol from an import into the - current scope: - ) - --------------------- -$(B alias) string.strlen strlen; --------------------- - - $(P - Aliases can also $(SINGLEQUOTE import) a set of overloaded functions, that can - be overloaded with functions in the current scope: - ) - --------------------- -class A { - int foo(int a) { return 1; } -} - -class B : A { - int foo( int a, uint b ) { return 2; } -} - -class C : B { - int foo( int a ) { return 3; } - $(B alias) B.foo foo; -} - -class D : C { -} - - -void test() -{ - D b = new D(); - int i; - - i = b.foo(1, 2u); // calls B.foo - i = b.foo(1); // calls C.foo -} --------------------- - - $(P - $(B Note:) Type aliases can sometimes look indistinguishable from - alias declarations: - ) - --------------------- -$(B alias) foo.bar abc; // is it a type or a symbol? --------------------- - - $(P - The distinction is made in the semantic analysis pass. - ) - - $(P Aliases cannot be used for expressions:) - ------------ -struct S { static int i; } -S s; - -alias s.i a; // illegal, s.i is an expression -alias S.i b; // ok -b = 4; // sets S.i to 4 ------------ - -Extern Declarations
- - Variable declarations with the storage class $(B extern) are - not allocated storage within the module. - They must be defined in some other object file with a matching - name which is then linked in. - The primary usefulness of this is to connect with global - variable declarations in C files. - -typeof
- -$(GRAMMAR -$(GNAME Typeof): - $(B typeof $(LPAREN)) $(EXPRESSION) $(B $(RPAREN)) - $(B typeof $(LPAREN)) $(B return) $(B $(RPAREN)) -) - - $(P - $(I Typeof) is a way to specify a type based on the type - of an expression. For example: - ) - --------------------- -void func(int i) { - $(B typeof)(i) j; // j is of type int - $(B typeof)(3 + 6.0) x; // x is of type double - $(B typeof)(1)* p; // p is of type pointer to int - int[$(B typeof)(p)] a; // a is of type int[int*] - - writefln("%d", $(B typeof)('c').sizeof); // prints 1 - double c = cast($(B typeof)(1.0))j; // cast j to double -} --------------------- - - $(P - $(I Expression) is not evaluated, just the type of it is - generated: - ) - --------------------- -void func() { - int i = 1; - $(B typeof)(++i) j; // j is declared to be an int, i is not incremented - writefln("%d", i); // prints 1 -} --------------------- - - $(P - There are $(V1 two) $(V2 three) special cases: - $(OL - $(LI $(B typeof(this)) will generate the type of what $(B this) - would be in a non-static member function, even if not in a member - function. - ) - $(LI Analogously, $(B typeof(super)) will generate the type of what - $(B super) would be in a non-static member function. - ) -$(V2 - $(LI $(B typeof(return)) will, when inside a function scope, - give the return type of that function. - ) -) - ) - ) - --------------------- -class A { } - -class B : A { - $(B typeof(this)) x; // x is declared to be a B - $(B typeof(super)) y; // y is declared to be an A -} - -struct C { - $(B typeof(this)) z; // z is declared to be a C* - $(B typeof(super)) q; // error, no super struct for C -} - -$(B typeof(this)) r; // error, no enclosing struct or class --------------------- - - $(P - Where $(I Typeof) is most useful is in writing generic - template code. - ) - -Void Initializations
- -$(GRAMMAR -$(GNAME VoidInitializer): - $(B void) -) - - $(P Normally, variables are initialized either with an explicit - $(I Initializer) or are set to the default value for the - type of the variable. If the $(I Initializer) is $(B void), - however, the variable is not initialized. If its value is - used before it is set, undefined program behavior will result. - ) - -------------------------- -void foo() { - int x = void; - writefln(x); // will print garbage -} -------------------------- - - $(P Therefore, one should only use $(B void) initializers as a - last resort when optimizing critical code. - ) - -Global and Static Initializers
- - $(P The $(GLINK Initializer) for a global or static variable must be - evaluatable at compile time. - Whether some pointers can be initialized with the addresses of other - functions or data is implementation defined. - Runtime initialization can be done with static constructors. - ) - -) - -Macros: - TITLE=Declarations - WIKI=Declaration - CATEGORY_SPEC=$0 - OPT=opt - ASSIGNEXPRESSION=$(GLINK2 expression, AssignExpression) - EXPRESSION=$(GLINK2 expression, Expression) - VEXPRESSION=$(V1 $(EXPRESSION))$(V2 $(ASSIGNEXPRESSION)) - FOO= diff --git a/deprecate.dd b/deprecate.dd index 42373cf30a..0b4e2870e1 100644 --- a/deprecate.dd +++ b/deprecate.dd @@ -2,56 +2,1068 @@ Ddoc $(SPEC_S Deprecated Features, - $(P Sometimes it becomes clear that a feature is just a bad idea. - These are called $(I deprecated features) and once they are judged - to merit removal from the language, they follow a procedure in - order to allow plenty of time for users to adjust to the change. - ) - - $(TABLE2 Deprecated Features, - $(THEAD Feature, Spec, Warn, Dep, Error, Gone) - $(TROW $(DEPLINK Base Class Protection), 2.058, , , , ) - ) - - $(DL - $(DT Spec) - $(DD Removal from the Specification) - $(DT Warn) - $(DD The compiler emits a warning if the feature is used) - $(DT Dep) - $(DD The compiler issues an error if not compiled with the -d switch) - $(DT Error) - $(DD It is an error to use the feature) - $(DT Gone) - $(DD The feature is completely gone) - ) - -$(DEPNAME Base Class Protection)
- - Base class protections are things like: + $(P Sometimes it becomes clear that a feature is just a bad idea. + These are called $(I deprecated features) and once they are judged + to merit removal from the language, they follow a procedure in + order to allow plenty of time for users to adjust to the change. + ) ---- -class A : $(B protected) B { - ... -} ---- + $(TABLE2 Deprecated Features, + $(THEAD Feature, Spec, Dep, Error, Gone) + $(TROW $(DEPLINK Throwing from contracts of nothrow functions), , 2.101, 2.111, ) + $(TROW $(COMMENT DEPLINK Hexstring literals), 2.079, 2.079, 2.086, ) + $(TROW $(DEPLINK Class allocators and deallocators), , 2.080, 2.087, 2.100 ) + $(TROW $(DEPLINK Implicit comparison of different enums), 2.075, 2.075, 2.081, ) + $(TROW $(DEPLINK Implicit string concatenation), 2.072, 2.072, 2.081, ) + $(TROW $(DEPLINK Using the result of a comma expression), 2.072, 2.072, 2.079, ) + $(TROW $(DEPLINK delete), , 2.079, 2.099, 2.109) + $(TROW $(DEPLINK scope as a type constraint), , 2.087, , ) + $(TROW $(DEPLINK Imaginary and complex types), future, 2.097, , ) + $(TROW $(DEPLINK 128-bit integer types), future, 2.100, 2.100, ) + $(TROW $(DEPLINK Implicit catch statement), 2.072, 2.072, 2.081, ) + $(TROW $(DEPLINK .sort and .reverse properties for arrays), ?, 2.072, , 2.075) + $(TROW $(DEPLINK C-style array pointers), ?, 2.072, 2.082, ) + $(TROW $(DEPLINK Floating point NCEG operators), 2.079, 2.066, 2.072, 2.080 ) + $(TROW $(DEPLINK clear), 2.060, 2.066, , 2.068 ) + $(TROW $(DEPLINK .min property for floating point types), N/A, 2.065, 2.067, 2.072 ) + $(TROW $(DEPLINK Cast T[] to integral type), ?, 2.060, , 2.061 ) + $(TROW $(DEPLINK Base Class Protection), 2.058, 2.058, 2.067, 2.072 ) + $(TROW $(DEPLINK Windows 3.x and Windows 9x support), 2.058, N/A, N/A, 2.058 ) + $(TROW $(DEPLINK typedef), 2.057, 2.057, 2.067, 2.072 ) + $(TROW $(DEPLINK Using * to dereference arrays), ?, 2.057, 2.067, (never) ) + $(TROW $(DEPLINK invariant as an alias for immutable), 2.057, 2.057, 2.064, 2.066 ) + $(TROW $(DEPLINK Non-final switch statements without a default case), 2.054, 2.054, 2.068, (never) ) + $(TROW $(DEPLINK Hiding base class functions), 2.054, 2.054, 2.068, (never) ) + $(TROW $(DEPLINK Octal literals), 2.054, 2.053, 2.067, (never) ) + $(TROW $(DEPLINK C-style function pointers), ?, 2.050, 2.067, (never) ) + $(TROW $(DEPLINK Using length in index expressions), ?, 2.041, , 2.061 ) + $(TROW $(DEPLINK Escape string literals), ?, 2.026, 2.061, 2.067 ) + $(TROW $(DEPLINK volatile), 2.013, 2.013, 2.067, 2.072) + $(TROW $(DEPLINK HTML source files), ?, 2.013, N/A, 2.061 ) + $(TROW $(DEPLINK Overriding without override), ?, 2.004, 2.072, (never) ) + $(TROW $(DEPLINK Lower case 'l' suffix for integer literals), ?, 1.054, 0.174, (never) ) + $(TROW $(DEPLINK Variable shadowing inside functions), ?, 0.161, , 2.061 ) + $(TROW $(DEPLINK Upper case 'I' suffix for imaginary literals), ?, 0.154, 2.061, (never) ) + $(TROW $(DEPLINK if (v; e)), ?, 0.149, 2.061, 2.068 ) + $(TROW $(DEPLINK Removing an item from an associative array with delete), ?, 0.127, 2.061, 2.067 ) + $(TROW $(DEPLINK .offset property), ?, 0.107, 2.061, 2.067 ) + $(TROW $(DEPLINK .size property), ?, 0.107, 0.107, 2.061 ) + $(TROW $(DEPLINK .typeinfo property), ?, 0.093, 2.061, 2.067 ) + $(TROW $(DEPLINK unannotated asm blocks), ,  , 2.100, (never) ) + $(TROW $(DEPLINK Throwing qualified objects), , 2.104,  , (never) ) + $(TROW $(DEPLINK Catching immutable/inout/shared objects), , 2.106,  , (never) ) + ) + + $(DL + $(DT Spec) + $(DD Removal from the Specification) + $(DT Dep) + $(DD The compiler warns by default, issues an error with the -de switch, and can be silenced with the -d switch) + $(DT Error) + $(DD It is an error to use the feature) + $(DT Gone) + $(DD The feature is completely gone) + ) + +$(H3 $(DEPNAME Throwing from contracts of nothrow functions)) + $(P Throwing exceptions from the contracts of a $(D nothrow) function was permitted: + --- + float sqrt(float n) nothrow + in + { + if (n < 0) + throw new Exception("n must be positive"); + } + do + { + // ... + } + --- + ) +$(H4 Corrective Action) + $(P Remove the $(D nothrow) attribute or rewrite the contract using + $(LINK2 spec/expression.html#assert_expressions, assertions) instead. + --- + float sqrt(float n) nothrow + in + { + assert(n >= 0); + } + do + { + // ... + } + --- + ) +$(H4 Rationale) + $(P Since a function's preconditions and postconditions are implicitly + executed before and after the function's body, allowing them to throw + would break the guarantees of the $(D nothrow) attribute. + ) + +$(COMMENT +$(H3 $(DEPNAME Hexstring literals)) + $(P Hexstring literals can be used to enter literals in base 16. + --- + // deprecated code + // auto x = x"1234"; + --- + ) +$(H4 Corrective Action) + $(P Use the $(REF hexString, std,conv) template. + --- + auto x = hexString!"1234"; + --- + ) +$(H4 Rationale) + $(P Hexstrings are used so seldom that they don't warrant a language feature. + ) +) + +$(H3 $(DEPNAME Class allocators and deallocators)) + $(P D classes can have members customizing the (de)allocation strategy. + --- + class Foo + { + new(uint size, ...) + { + return malloc(size); + } + + delete(void* obj) + { + free(obj); + } + } + + Foo foo = new(...) Foo(); + delete foo; + --- + ) +$(H4 Corrective Action) + $(P Move the (de)allocation strategy out of the class + --- + class Foo + { + } + + T make(T, Args...)(auto ref Args args) if (is(T == Foo)) + { + enum size = __traits(classInstanceSize, T); + void* mem = malloc(size); + scope (failure) free(mem); + return mem !is null ? emplace!T(mem[0..size], args) : null; + } + + void dispose(T)(T obj) + { + auto mem = cast(void*) obj; + scope (exit) free(mem); + destroy(obj); + } + + Foo foo = make!Foo(); + if (foo !is null) dispose(foo); + --- + ) +$(H4 Rationale) + $(P Classes should not be responsible for their own (de)allocation strategy. + ) + +$(H3 $(DEPNAME Implicit comparison of different enums)) + $(P Comparison of different enumerated type was allowed: + --- + enum Status + { + good, + bad + } + enum OtherStatus + { + ok, + no + } + static assert(Status.good == OtherStatus.ok); + --- + ) +$(H4 Corrective Action) + $(P Comparison between unrelated enumerated types should be done with $(REF asOriginalType, std, conv)) + --- + import std.conv : asOriginalType; + assert(Foo.x.asOriginalType == Bar.y.asOriginalType); + --- +$(H4 Rationale) + $(P Code correctness is improved by + disallowing comparison of unrelated enumerated types. Implicit comparison of + different `enum` types often resulted in hard to spot bugs.) + + --- + enum { X } + enum { Y } + void main() { + auto b = X == Y; + assert(b); + } + --- + +$(H3 $(DEPNAME Implicit string concatenation)) + $(P Two adjacent strings were implicitly concatenated: + + --- + string foo = "Hello" "World"; + --- + + This feature was handy for a long string that spans multiple lines, + however, it is possible to get the same behaviour explicitly by + using the concatenation operator ('~'): + + --- + string foo = "Hello" ~ "World"; // No allocation is performed + --- + ) +$(H4 Corrective Action) + $(P Replace implicit string concatenation by explicit one, using '~'.) +$(H4 Rationale) + $(P This is a very early feature of the language, which is nowadays totally + covered by the concatenation operator: it is performed at compile time + for constants and doesn't result in memory allocation.) + + $(P However, having implicit concatenation can and did result in hard + to spot bugs, for example:) + + --- + string[] names = + [ + "Anna", + "Michael" + "Emma", + "David" + ]; + // The content of arr is [ "Anna", "MichaelEmma", "David" ] + --- + +$(H3 $(DEPNAME Using the result of a comma expression)) + $(P The comma operator (`,`) allows executing multiple expressions and + discards the result of them except for the last which is returned. + + --- + int a = 1; + int b = 2; + bool ret = a == 2, b == 2; // true + --- + + It's also common to use the comma operator in for-loop increment + statements to allow multiple expressions. + + --- + for (; !a.empty && !b.empty; a.popFront, b.popFront) + --- + ) +$(H4 Corrective Action) + $(P If possible, split the comma operator in two statements. Otherwise use + lambdas. + + --- + auto result = foo(), bar(); + + // split off in two statements + foo(); + auto result = bar(); + + // or use lambdas + auto result = {foo(); return bar();}(); + --- + ) +$(H4 Rationale) + $(P The comma operator leads to unintended behavior (see below for a selection) + Moreover it is not commonly used and it blocks the ability to implement tuples. + + A selection of problems through the accidental use of the comma operator: + --- + writeln( 6, mixin("7,8"), 9 ); // 6, 8, 9 + + template vec(T...)(T args) { ... } + vec v = (0, 0, 3); // 3, because vec is variadic + + int b = 2; + if (a == 1, b == 2) { + // will always be reached + } + + void foo(int x) {} + foo((++a, b)); + + synchronized (lockA, lockB) {} + // isn't currently implemented, but still compiles due to the comma operator + --- + ) + +$(H3 $(DEPNAME delete)) + $(P Memory allocated on the GC heap can be freed with $(D delete). + --- + auto a = new Class(); + delete a; + --- + ) +$(H4 Corrective Action) + $(P Use $(LINK2 phobos/object.html#.destroy, $(D object.destroy())) + to finalize the object instead. + --- + auto a = new Class(); + destroy(a); + --- + ) + $(P Note that $(D destroy) does not free the allocated memory. If + necessary, call $(LINK2 phobos/core_memory.html#.GC.free, $(D core.GC.free)) also. + ) +$(H4 Rationale) + $(P $(D delete) makes assumptions about the type of garbage collector + available that limits which implementations can be used, and can be + replaced by a library solution. + ) + + + +$(H3 $(DEPNAME scope as a type constraint)) + $(P + The `scope` keyword can be added to a class declaration to force all instances of the + class to be attributed with the `scope` storage class. + + --- + scope class C { } // `scope` type constraint. This usage of `scope` is deprecated. + + void main() + { + C c1 = new C(); // Error: reference to `scope class` must be `scope` + // This error is due to the `scope` attribution on the declaration + // of `class C` and the missing `scope` storage class attribution + // on `c1`. + + scope C c2 = new C(); // OK because the instance `c2` is attributed with the `scope` + // storage class. This usage of `scope` is not deprecated. + } + --- + ) +$(H4 Corrective Action) + There is no current counterpart in the D programming language or library that places such a + constraint on a type requiring all instances of the type to be attributed with the `scope` + storage class. + +$(H4 Rationale) + $(P + `scope` as a type constraint was a quirk in the language without a compelling + use case. + ) + $(P + Note that this deprecation only affects the usage of `scope` as a type constraint + attributed to a class declaration. `scope` as a storage class attributed to variables, + function parameters, etc. is not deprecated. + ) + + +$(H3 $(DEPNAME Imaginary and complex types)) + $(P D currently supports imaginary and complex versions of all floating point types. + --- + float a = 2; + ifloat b = 4i; + cfloat c = a + b; + assert(c == 2 + 4i); + --- + ) +$(H4 Corrective Action) + $(P Use the library types in $(STDFILEREF complex). + ) +$(H4 Rationale) + $(P These types are too specialized to be a part of the core language. + ) + + +$(H3 $(DEPNAME 128-bit integer types)) + $(P D currently reserves the `cent` and `ucent` keywords for future use as + 128-bit integral types. Using them will result in a compile-time error. + ) + --- + cent a = 18446744073709551616L; + ucent b = 36893488147419103232UL; + --- + +$(H4 Corrective Action) + $(P Use the library types in $(MREF std, int128) or $(COREFILEREF int128). + ) +$(H4 Rationale) + $(P These types are too specialized to be a part of the core language. + ) + + +$(H3 $(DEPNAME Implicit catch statement)) + $(P One can catch everything by using $(D catch) without specifying a type.) + --- + int[] arr = new int[](10); + // This will throw a RangeError + try { arr[42]++; } + catch { writeln("An error was caught and ignored"); } + --- + +$(H4 Corrective Action) + $(P Either don't catch `Throwable` or replace `catch {}` with `catch (Throwable) {}`) + --- + int[] arr = new int[](10); + // This will throw a RangeError + try { arr[42]++; } + catch (Throwable) { writeln("An error was caught and ignored"); } + --- + +$(H4 Rationale) + $(P Catching `Throwable` should not be encouraged by the language, + because certain core guarantee cannot be satisfied, e.g. the stack might not get cleaned + up and destructors might not get run. + This change helps ensure catching `Throwable` is always a conscious and visible decision + on the programmer's side. + ) + + +$(H3 $(DEPNAME .sort and .reverse properties for arrays)) + $(P D arrays can be manipulated using these built-in properties. + --- + int[] x = [2, 3, 1]; + assert(x.sort == [1, 2, 3]); + --- + ) +$(H4 Corrective Action) + $(P Use the generic functions in $(STDFILEREF algorithm). + ) +$(H4 Rationale) + $(P These operations are better implemented in the standard library. + ) + + + +$(H3 $(DEPNAME C-style array pointers)) + $(P C-style array pointers can be used in D. + --- + alias float *arrayptr[10][15]; + --- + ) +$(H4 Corrective Action) + $(P Replace with D-style array pointers. + --- + alias float[15][10]* arrayptr; + --- + ) +$(H4 Rationale) + $(P The D syntax is much cleaner and easier to use. + ) + + + +$(H3 $(DEPNAME Floating point NCEG operators)) + $(P D currently supports the NCEG floating point operators + (!<>=, <>, <>=, !>, !>=, !<, !<=, !<>) for comparisons involving NaNs. + ) +$(H4 Corrective Action) + $(P Use the normal operators and $(REF isNaN, std,math,traits). + ) +$(H4 Rationale) + $(P These operators are too specialized to be a part of the core language. + ) + + + +$(H3 $(DEPNAME clear)) + $(P Call an object's destructor. + --- + auto a = new Class(); + clear(a); + --- + ) +$(H4 Corrective Action) + $(P Use $(LINK2 phobos/object.html#.destroy, $(D object.destroy())) instead. + --- + auto a = new Class(); + destroy(a); + --- + ) +$(H4 Rationale) + $(P Due to Uniform Function Call Syntax (UFCS), $(D clear) can cause + confusion with other methods of the same name, such as a $(D clear) + method used to remove the contents of a container. + ) + + + +$(H3 $(DEPNAME .min property for floating point types)) + $(P Floating point types have the .min property to access the smallest value. + --- + enum m = real.min; + --- + ) +$(H4 Corrective Action) + $(P Replace with .min_normal + --- + enum m = real.min_normal; + --- + ) +$(H4 Rationale) + $(P The name min_normal is more accurate, as .min does not include + denormalized floating point values. + ) + + + +$(H3 $(DEPNAME Cast T[] to integral type)) + $(P At some point in time you could do: + --- + ulong u = cast(ulong)[1,2]; + --- + To get the length of the array. + ) +$(H4 Corrective Action) + $(P Use the $(LINK2 https://dlang.org/spec/arrays.html#array-properties, .length) + property instead. + ) +$(H4 Rationale) + $(P Using a cast to get the length of an array is just confusing. + ) + + + +$(H3 $(DEPNAME Base Class Protection)) + $(P Base class protections are things like: + --- + class A : $(D protected) B + { + ... + } + --- + ) +$(H4 Corrective Action) + $(P Delete the protection attribute keyword from in front of the base class + and base interfaces. + ) +$(H4 Rationale) + $(P With D's module system, it doesn't seem to serve any useful purpose, and + has never worked correctly. + ) + + + +$(H3 $(DEPNAME Windows 3.x and Windows 9x support)) + $(P There is some code in Phobos for Windows 3.x/9x support. + ) +$(H4 Corrective Action) + $(P Upgrade Windows or switch to another supported OS. + ) +$(H4 Rationale) + $(P Supporting such outdated and rarely used OS-es isn't worth the trouble. + ) -Corrective Action
- $(P Delete the protection attribute keyword from in front of the base class - and base interfaces. - ) -Rationale
+$(H3 $(DEPNAME typedef)) + $(P typedef can be used to construct a strongly-typed alias of a type. + --- + typedef int myint; + static assert(!is(myint == int)); + --- + ) +$(H4 Corrective Action) + $(P Replace use of typedef with alias or use $(REF Typedef, std,typecons). + ) +$(H4 Rationale) + $(P typedef is not flexible enough to cover all use cases. This is better + done with a library solution. + ) - $(P With D's module system, it doesn't seem to serve any useful purpose.) + +$(H3 $(DEPNAME Using * to dereference arrays)) + $(P D array variables can be dereferenced to get the first element, much like pointers. + --- + int[] arr = [1, 2, 3]; + assert(*arr == 1); + --- + ) +$(H4 Corrective Action) + $(P Use indexing syntax to access first member. + --- + int[] arr = [1, 2, 3]; + assert(arr[0] == 1); + --- + ) +$(H4 Rationale) + $(P D arrays are not pointers. + ) + + + +$(H3 $(DEPNAME invariant as an alias for immutable)) + $(P The invariant storage class and type modifier is an alias for immutable. + --- + static assert(is(invariant(int) == immutable(int))); + --- + ) +$(H4 Corrective Action) + $(P Replace all uses of invariant as a storage class or type modifier with + immutable. The invariant() syntax for struct and class invariants is + still supported. + ) +$(H4 Rationale) + $(P The alias is unnecessary. + ) + + + +$(H3 $(DEPNAME Non-final switch statements without a default case)) + $(P Switch statements can be declared without a default case, and the + compiler automatically adds one. + --- + switch(a) + { + case 1: + break; + case 2: + break; + // the compiler adds + // default: + // throw new SwitchError(); + } + --- + ) +$(H4 Corrective Action) + $(P Add the default case manually. + --- + switch(a) + { + case 1: + break; + case 2: + break; + default: + assert(0); + } + --- + ) +$(H4 Rationale) + $(P Missing default cases can hide bugs, and making the default case + explicit should be mandatory. + ) + + + +$(H3 $(DEPNAME Hiding base class functions)) + $(P This occurs when declaring a function in a derived class that can be called with the + same arguments as a function in a base class, without overriding that + function. The base class function gets hidden: + --- + class A + { + void fun(int x) {} + } + class B : A + { + void fun(long x) {} + } + --- + ) +$(H4 Corrective Action) + $(P Add the function to the base class, or use an alias to bring the base + class overload into the derived class: + --- + class A + { + void fun(int x) {} + void fun(long x) {} // this fixes it + } + class B : A + { + void fun(long x) {} + alias A.fun fun; // so does this + } + --- + ) +$(H4 Rationale) + $(P This is an error that is already detected at runtime, and is being + extended to compile time. + ) + + + +$(H3 $(DEPNAME Octal literals)) + $(P Octal literals can be used to enter literals in base 8. + --- + // deprecated code + // auto x = 0123; + --- + ) +$(H4 Corrective Action) + $(P Use the $(REF octal, std,conv) template. + --- + auto x = octal!123; + --- + ) +$(H4 Rationale) + $(P The use of a leading zero is confusing, as 0123 != 123. + ) + + + +$(H3 $(DEPNAME C-style function pointers)) + $(P C-style function pointers can be used in D. + --- + alias void(*fptr)(int, long); + --- + ) +$(H4 Corrective Action) + $(P Replace with D-style function pointers. + --- + alias void function(int, long) fptr; + --- + ) +$(H4 Rationale) + $(P The D syntax is much cleaner and easier to use. + ) + + + +$(H3 $(DEPNAME Using length in index expressions)) + $(P When used inside an indexing or slicing expression, length is rewritten to + be the length of the array being sliced. + --- + auto a = new int[5]; + a = a[0..length-1]; + --- + ) +$(H4 Corrective Action) + $(P Replace length with the equivalent $(LINK2 spec/arrays.html#array-length, '$') + ) +$(H4 Rationale) + $(P The implicitly defined length variable shadows existing declarations, + and is less concise than the alternative. + ) + + + +$(H3 $(DEPNAME Escape string literals)) + $(P Escape string literals can be used to describe characters using escape sequences. + --- + // deprecated code + // string x = "hello" ~ \n; + --- + ) +$(H4 Corrective Action) + $(P Put escape sequences inside a regular string literal. + --- + string x = "hello\n"; + --- + ) +$(H4 Rationale) + $(P Escape string literals are unintuitive and unnecessary. + ) + + + +$(H3 $(DEPNAME volatile)) + $(P volatile can be used to mark statement, in order to prevent some + compiler optimizations. + --- + volatile + { + ... do something involving ghared variables ... + } + --- + ) +$(H4 Corrective Action) + $(P Convert the code to use synchronized statements instead. + ) +$(H4 Rationale) + $(P volatile statements are a misfeature. + ) + + + +$(H3 $(DEPNAME HTML source files)) + $(P The D compiler can parse html files by ignoring everything not contained + in <code></code> tags. + --- + +
+ ... source ...
+
+
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Extract code to regular source files.
+ )
+$(H4 Rationale)
+ $(P This has been replaced for documentation by the introduction of ddoc
+ )
+
+
+
+$(H3 $(DEPNAME Overriding without override))
+ $(P Virtual functions can currently override a function in a base class
+ without the 'override' attribute.
+ ---
+ class A
+ {
+ void fun() {}
+ }
+ class B : A
+ {
+ // overrides but is not marked with override
+ void fun() {}
+ }
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Mark overriding functions with $(D override)
+ ---
+ class A
+ {
+ void fun() {}
+ }
+ class B : A
+ {
+ override void fun() {}
+ }
+ ---
+ )
+$(H4 Rationale)
+ $(P Making the $(D override) attribute mandatory makes it explicit, and can
+ catch errors when a base class function is accidentally overridden.
+ )
+
+
+
+$(H3 $(DEPNAME Lower case 'l' suffix for integer literals))
+ $(P Lower case 'l' is an alternative suffix to denote 64 bit integer literals.
+ ---
+ // deprecated code
+ // auto x = 123l;
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Use the upper case 'L' suffix.
+ ---
+ auto x = 123L;
+ ---
+ )
+$(H4 Rationale)
+ $(P The lower case suffix is easily confused with the digit '1'.
+ )
+$(H4 Note)
+ $(P In lexical analysis phase, compiler can recognize lower case suffix 'l'
+ to report better error message - for the use case such as C-to-D code
+ translation. Thus DMD would continue to parse 'l' suffix.
+ )
+
+
+
+$(H3 $(DEPNAME Variable shadowing inside functions))
+ $(P Variable shadowing is when a variable in an inner scope has the same
+ name as a variable in an enclosing scope.
+ ---
+ void myFun()
+ {
+ int var;
+ if (x)
+ {
+ int var;
+ var = 3; // which var was meant?
+ }
+ }
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Rename shadowing variables so they don't conflict.
+ )
+$(H4 Rationale)
+ $(P Variable shadowing can introduce hard to find bugs where the wrong
+ variable is modified.
+ )
+
+
+
+$(H3 $(DEPNAME Upper case 'I' suffix for imaginary literals))
+ $(P The 'I' suffix can be used to denote imaginary floating point values.
+ ---
+ // deprecated code
+ // auto x = 1.234I;
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Use the lower case 'i' suffix.
+ ---
+ auto x = 1.234i;
+ ---
+ )
+$(H4 Rationale)
+ $(P The 'I' suffix is easily confused with the digit '1'.
+ )
+
+
+
+$(H3 $(DEPNAME if (v; e)))
+ $(P This syntax can be used to declare a variable in an if statement condition.
+ ---
+ if (v; calculateAndReturnPointer()) { ... }
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Replace with an auto declaration.
+ ---
+ if (auto v = calculateAndReturnPointer()) { ... }
+ ---
+ )
+$(H4 Rationale)
+ $(P The syntax is clearer with auto.
+ )
+
+
+
+$(H3 $(DEPNAME Removing an item from an associative array with delete))
+ $(P delete can be used to remove an item from an associative array.
+ ---
+ int[int] aa = [1 : 2];
+ delete aa[1];
+ assert(1 !in aa);
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Use .remove instead.
+ ---
+ int[int] aa = [1 : 2];
+ aa.remove(1);
+ assert(1 !in aa);
+ ---
+ )
+$(H4 Rationale)
+ $(P The delete syntax is confusing and conflicts with the normal delete syntax.
+ )
+
+
+
+$(H3 $(DEPNAME .offset property))
+ $(P The .offset property can be used to get member offset information.
+ ---
+ struct S { int a, b; }
+ static assert(S.b.offset == 4);
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Use .offsetof instead
+ ---
+ struct S { int a, b; }
+ static assert(S.b.offsetof == 4);
+ ---
+ )
+$(H4 Rationale)
+ $(P The .offset syntax has been superseded by .offsetof
+ )
+
+
+
+$(H3 $(DEPNAME .size property))
+ $(P The .size property can be used to get type size information
+ ---
+ struct S { int a, b; }
+ static assert(S.size == 8);
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Use .sizeof instead
+ ---
+ struct S { int a, b; }
+ static assert(S.sizeof == 8);
+ ---
+ )
+$(H4 Rationale)
+ $(P The .size syntax has been superseded by .sizeof
+ )
+
+
+
+$(H3 $(DEPNAME .typeinfo property))
+ $(P The .typeinfo property can be used to get the associated TypeInfo class.
+ ---
+ T.typeinfo
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Use typeid() instead
+ ---
+ typeid(T)
+ ---
+ )
+$(H4 Rationale)
+ $(P The .typeinfo syntax has been superseded by typeid()
+ )
+
+
+
+$(H3 $(DEPNAME unannotated asm blocks))
+ $(P $(D asm) blocks don't affect the function annotations.
+ ---
+ void foo() @safe
+ {
+ asm { noop; }
+ }
+ ---
+ )
+$(H4 Corrective Action)
+ $(P Annotate the $(D asm) blocks instead
+ ---
+ void foo() @safe
+ {
+ asm @trusted { noop; }
+ }
+ ---
+ )
+$(H4 Rationale)
+ $(P $(D asm) blocks may throw, contain unsafe, impure code or call the GC
+ interfaces.)
)
-Macros:
- DEPLINK=$(LINK2 #$0, $0)
- DEPLINK2=$(LINK2 $1.html#$2, $2)
- DEPNAME=$(LNAME2 $0, $0)
- TITLE=Deprecated Features
- WIKI=DeprecatedFeatures
+$(H3 $(DEPNAME Throwing qualified objects))
+
+$(P
+Previously, an `immutable`, `const`, `inout` or `shared` exception could be
+thrown and then caught in an unqualified `catch (Exception e)` clause.
+That breaks type safety.
+Throwing a qualified object is now deprecated. This helps to prevent
+possible mutation of an immutable object in a `catch` clause.
+)
+
+$(P
+The runtime also modifies a thrown object (e.g. to contain a stack
+trace) which can violate `const` or `immutable` objects. Throwing
+qualified objects has been deprecated for this reason also.
+)
+$(H3 $(DEPNAME Catching immutable/inout/shared objects))
+
+$(P
+It is unsafe to catch an exception as `immutable`, `inout` or `shared`.
+This is because the exception may still be accessible through another
+mutable or non-shared reference.
+)
+
+---
+auto e = new Exception("first");
+try {
+ throw e;
+} catch(immutable Exception ie) { // unsafe
+ e.msg = "second";
+ assert(ie.msg == "first"); // would fail
+}
+---
+
+
+Macros:
+ DEPLINK=$(RELATIVE_LINK2 $0, $0)
+ DEPLINK2=$(LINK2 $1.html#$2, $2)
+ DEPNAME=$(LNAME2 $0, $0)
+ TITLE=Deprecated Features
+ STDFILEREF = $(D std.$1)
+ COREFILEREF = $(D core.$1)
diff --git a/dlang.org.ddoc b/dlang.org.ddoc
new file mode 100644
index 0000000000..3028e24405
--- /dev/null
+++ b/dlang.org.ddoc
@@ -0,0 +1,590 @@
+_=Macros for the dlang.org site look and feel. Please keep sorted by name. Multiline macros should keep one _= line before and after for clarity. Also, one _= line should be present when the first letter changes. (The "_="" is needed so there's no extra newline after the last macro defined in a group.)
+
+ACRONYM = $1 ($+)
+ACC = $(GLOSSARY2 acc, Associated C Compiler)
+ASSIGNEXPRESSION = $(GLINK2 expression, AssignExpression)
+_=
+
+BIGOH = $(SPANC bigoh, Ο($(D $0)))
+BLOCKQUOTE = $(T blockquote, $(P $0))
+BLOCKQUOTE_BY = $(BLOCKQUOTE $+ $(T cite, $1))
+BLACK=$(SPANC black, $0)
+BLUE=$(SPANC blue, $0)
+BODY_PREFIX=
+BOOKTABLE = $(TC table, book, $(T caption, $1)$+)
+BUGZILLA = $(SPANC bugzilla, $(AHTTPS issues.dlang.org/show_bug.cgi?id=$0, Bugzilla $0))
+BUGZILLA_NEW_BUG_URL=https://github.com/dlang/$(PROJECT)/issues/new?title=%5B$(TITLE)%5D%20
+_=
+
+CCODE=$(TC pre, ccode notranslate, $0)
+CODE=$(D $0)
+CODE_AMP=$(D &)
+CODE_DOLLAR=$(D $)
+CODE_HIGHLIGHT=$(B $(I $0))
+CODE_LCURL=$(D {)
+CODE_PERCENT=$(D %)
+CODE_PIPE=$(D |)
+CODE_RCURL=$(D })
+_=
+
+COMMON_HEADERS_DLANG=
+
+_=
+COMMON_SCRIPTS =
+ $(SCRIPTLOAD https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js)
+ $(SCRIPT window.jQuery || document.write('\x3Cscript src="https://github.com/$(STATIC%20js/jquery-1.7.2.min.js)">\x3C/script>');$(EXTRA_JS))
+ $(SCRIPTLOAD $(STATIC js/dlang.js))
+ $(COMMON_SCRIPTS_DLANG)
+_=
+COMMON_SCRIPTS_DLANG =
+ $(SCRIPTLOAD $(STATIC js/codemirror-compressed.js))
+ $(SCRIPTLOAD $(STATIC js/run.js))
+_=
+
+COMPATIBILITY_BOX_DEPRECATED = $(MESSAGE_BOX red, $(B Deprecated) - $0)
+COMPATIBILITY_BOX_SUPERSEDED = $(MESSAGE_BOX gray, $(B Obsolete) - $0)
+COMPATIBILITY_BOX_OBSOLETE = $(MESSAGE_BOX gray, $(B Obsolete) - $0)
+COMPATIBILITY_BOX_OUTDATED = $(MESSAGE_BOX gray, $(B Obsolete) - $0)
+COMPATIBILITY_BOX_EXPERIMENTAL = $(MESSAGE_BOX orange, $(B Experimental) - $0)
+_=
+
+CONSOLE=$(TC pre, console notranslate, $0)
+COPYRIGHT_FOUNDATION=Copyright © 1999-$(YEAR) by the $(LINK2 $(ROOT_DIR)foundation_overview.html, D Language Foundation)
+CPPCODE=$(TC pre, cppcode notranslate, $0)
+CPPLISTING=$(CPPCODE $0)
+CROSS=✘
+_=
+
+D=$(SPANC d_inlinecode donthyphenate notranslate, $0)
+D_CODE=$(TC pre, d_code notranslate, $0)
+OTHER_CODE=$(TC pre, $1code notranslate, $+)
+_=
+
+DDOC=
+
+
+
+
+
+
+
+$(T title, $(FULL_TITLE))
+$(COMMON_HEADERS_DLANG)
+
+
+
+
+$(EXTRA_HEADERS)
+
+
+$(SCRIPT document.body.className += ' have-javascript')
+$(DIVID top, $(DIVC helper, $(DIVC helper expand-container,
+ $(DIVC logo, $(SPANC key keySection, $0)$(LF) +DDOC_SECTION = $(DIVC val, $0
)$(LF) +DDOC_PARAM_ROW =$0
+RUNNABLE_EXAMPLE_ARGS=$0
+
+SCINI=$(TC pre, scini notranslate, $0)
+SCRIPTLOAD=
+SEARCHDEFAULT_PHOBOS=
+SEARCHDEFAULT_FORUM=
+SEARCHDEFAULT_SPEC=
+SEARCH_BOX=
+ $(DIVID search-box,
+
+ )
+SEARCH_OPTIONS_EXTRA=
+_=
+
+SECTION1=$(H1 $1)$+
+SECTION2=$(H2 $1)$+
+SECTION3=$(H3 $1)$+
+SECTION4=$(H4 $1)$+
+SECTION5=$(H5 $1)$+
+_=
+
+$(COMMENT
+ SIMPLE_CHEATSHEET is used for cheat sheets that play the same role
+ as the listings generated by DDOX. Consequently, DDOX hides these cheat
+ sheets.
+)
+SIMPLE_CHEATSHEET=$(TC table, simple-cheatsheet, $(T caption, Cheat Sheet) $0)
+_=
+
+SLASH_PREFIXED=/$1$(SLASH_PREFIXED $+)
+
+
+SRC_FILENAME=$(SRCFILENAME)
+STATIC=$(ROOT_DIR)$1
+SUBMENU=DLLs with a C Interface
- - $(P A DLL presenting a C interface can connect to any other code - in a language that supports calling C functions in a DLL. - ) - - $(P DLLs can be created in D in roughly the same way as in C. - A $(D DllMain()) - is required, looking like: - ) - --------------------------------- -import std.c.windows.windows; -import core.sys.windows.dll; - -__gshared HINSTANCE g_hInst; - -extern (Windows) -BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) -{ - switch (ulReason) - { - case DLL_PROCESS_ATTACH: - g_hInst = hInstance; - dll_process_attach( hInstance, true ); - break; - - case DLL_PROCESS_DETACH: - dll_process_detach( hInstance, true ); - break; - - case DLL_THREAD_ATTACH: - dll_thread_attach( true, true ); - break; - - case DLL_THREAD_DETACH: - dll_thread_detach( true, true ); - break; - } - return true; -} - -------------------------------- - - $(P Notes:) - $(UL - $(LI DllMain simply forwards to the appropriate helper functions. These setup - the runtime, create thread objects for interaction with the garbage collector - and initialize thread local storage data.) - $(LI The DLL does not share its runtime or memory with other DLLs.) - $(LI The first boolean argument to the dll-helper functions specify whether all threads - should be controlled by the garbage collector. You might need more control over - this behaviour if there are threads in the process that must not be suspended. - In this case pass false to disable the automatic handling of all threads.) - $(LI The presence of $(D DllMain()) is recognized by the compiler - causing it to emit a reference to - $(LINK2 http://www.digitalmars.com/ctg/acrtused.html, __acrtused_dll) - and the $(TT phobos.lib) runtime library.) - ) - - Link with a .def - ($(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, Module Definition File)) - along the lines of: - -$(MODDEFFILE -LIBRARY MYDLL -DESCRIPTION 'My DLL written in D' - -EXETYPE NT -CODE PRELOAD DISCARDABLE -DATA WRITE - -EXPORTS - DllGetClassObject @2 - DllCanUnloadNow @3 - DllRegisterServer @4 - DllUnregisterServer @5 -) - - $(P The functions in the EXPORTS list are for illustration. - Replace them with the actual exported functions from MYDLL. - Alternatively, use - $(LINK2 http://www.digitalmars.com/ctg/implib.html, implib). - Here's an example of a simple DLL with a function print() - which prints a string: - ) - -mydll.d:
-------------------------------- -module mydll; -import std.c.stdio; -export void dllprint() { printf("hello dll world\n"); } -------------------------------- - - $(P Note: We use $(CODE printf)s in these examples - instead of $(CODE writefln) - to make the examples as - simple as possible.) - -mydll.def:
- -$(MODDEFFILE -LIBRARY "mydll.dll" -EXETYPE NT -SUBSYSTEM WINDOWS -CODE SHARED EXECUTE -DATA WRITE -) - - $(P Put the code above that contains $(CODE DllMain()) into a file - $(TT dll.d). - Compile and link the dll with the following command: - ) - -$(CONSOLE -C:>dmd -ofmydll.dll -L/IMPLIB mydll.d dll.d mydll.def -C:> -) - - $(P 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; -} -------------------------------- - - $(P Create an interface file mydll.di that doesn't have the function bodies:) - -mydll.di:
-------------------------------- -export void dllprint(); -------------------------------- - - Compile and link with the command: - -$(CONSOLE -C:>dmd test.d mydll.lib -C:> -) - - and run: -$(CONSOLE -C:>test -hello dll world -C:> -) - - - -Memory Allocation
- - $(P 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. - ) - - $(P There are many approaches to solving this problem:) - - $(UL - - $(LI 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.) - - $(LI 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.) - - $(LI Notify the GC about external references to a memory block by - calling GC.addRange.) - - $(LI Use operating system primitives like VirtualAlloc() to allocate - memory to be transferred between DLLs.) - - $(LI 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 - $(LINK2 http://www.amazon.com/exec/obidos/ASIN/1556158432/classicempire, 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 core.runtime; -import std.c.stdio; -import std.c.stdlib; -import std.string; -import std.c.windows.windows; - -HINSTANCE g_hInst; - -extern (C) -{ - void gc_setProxy(void* p); - void gc_clrProxy(); -} - -extern (Windows) - BOOL $(B DllMain)(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) -{ - switch (ulReason) - { - case DLL_PROCESS_ATTACH: - printf("DLL_PROCESS_ATTACH\n"); - Runtime.initialize(); - break; - - case DLL_PROCESS_DETACH: - printf("DLL_PROCESS_DETACH\n"); - Runtime.terminate(); - 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 $(B MyDLL_Initialize)(void* gc) -{ - printf("MyDLL_Initialize()\n"); - gc_setProxy(gc); -} - -export void $(B MyDLL_Terminate)() -{ - printf("MyDLL_Terminate()\n"); - gc_clrProxy(); -} - -$(B static this)() -{ - printf("static this for mydll\n"); -} - -$(B static ~this)() -{ - printf("static ~this for mydll\n"); -} - -/* --------------------------------------------------------- */ - -class $(B MyClass) -{ - char[] $(B concat)(char[] a, char[] b) - { - return a ~ " " ~ b; - } - - void $(B free)(char[] s) - { - delete s; - } -} - -export MyClass $(B getMyClass)() -{ - return new MyClass(); -} -------------------------------- - -
-
-
- $(B DllMain) -
- This is the main entry point for any D DLL. It gets called
- by the C startup code
- (for DMC++, the source is $(TT \dm\src\win32\dllstart.c)).
- The $(B 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 is in this version as well.
- This is because the same DLL should be usable from both C and
- D programs, so the same initialization process should work
- for both.
-
- -
- $(B MyDLL_Initialize) -
-
- When the DLL is dynamically linked via $(B Runtime.loadLibrary)()
- the runtime makes sure that any initialization steps required
- by the D program are executed after the library is loaded. If
- the library is statically linked, this routine is not called by
- the program, so to make sure the DLL is initialized properly we
- have to do some of the work ourselves. And because the library
- is being statically linked, we need a function specific to this
- DLL to perform the initialization.
- This function takes one argument, a handle to the
- caller's gc. We'll see how that handle is obtained later.
- To pass this handle to the runtime and override the DLL's built-in
- gc we'll call $(B gc_setProxy)().
- The function is $(B export)ed as that is how a function is made
- visible outside of a DLL.
-
- -
- $(B MyDLL_Terminate) -
- Correspondingly, this function terminates the DLL, and is
- called prior to unloading it.
- It has only one job: informing the runtime that the DLL will
- no longer be using the caller's gc via $(B gc_clrProxy)().
- This 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.
-
- -
- $(B 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.
-
- -
- $(B MyClass) -
- This is an example of a class that can be exported from
- and used by the caller of a DLL. The $(B concat) member
- function allocates some gc memory, and $(B free) frees gc
- memory.
-
- -
- $(B getMyClass) -
- An exported factory that allocates an instance of $(B MyClass)
- and returns a reference to it.
-
- -
Compiles $(D mydll.d) into $(TT mydll.obj). - $(B -g) turns on debug info generation. - ) - - $(LI $(B $(TT dmd mydll.obj mydll.def -g -L/map)) -
Links $(TT mydll.obj) into a DLL named $(TT mydll.dll). - $(TT mydll.def) is the - $(LINK2 http://www.digitalmars.com/ctg/ctgDefFiles.html, Module Definition File), - and has the contents: - -$(MODDEFFILE -LIBRARY MYDLL -DESCRIPTION 'MyDll demonstration DLL' -EXETYPE NT -CODE PRELOAD DISCARDABLE -DATA PRELOAD MULTIPLE -) - $(B -g) turns on debug info generation, and - $(B -L/map) generates a map file $(TT mydll.map). - ) - - $(LI $(B $(TT implib /noi /system mydll.lib mydll.dll)) -
Creates an - $(LINK2 http://www.digitalmars.com/ctg/implib.html, import library) - $(TT mydll.lib) suitable - for linking in with an application that will be statically - loading $(TT mydll.dll). - ) - - ) - - $(P Here's $(TT test.d), a sample application that makes use of - $(TT mydll.dll). There are two versions, one statically binds to - the DLL, and the other dynamically loads it. - ) - -------------------------------- -import core.runtime; -import std.stdio; -import std.gc; - -import mydll; - -//version=DYNAMIC_LOAD; - -version (DYNAMIC_LOAD) -{ - import std.c.windows.windows; - - alias MyClass function() getMyClass_fp; - - int main() - { HMODULE h; - FARPROC fp; - - getMyClass_fp getMyClass; - MyClass c; - - printf("Start Dynamic Link...\n"); - - h = cast(HMODULE) Runtime.loadLibrary("mydll.dll"); - if (h is null) - { - printf("error loading mydll.dll\n"); - return 1; - } - - fp = GetProcAddress(h, "D5mydll10getMyClassFZC5mydll7MyClass"); - if (fp is null) - { printf("error loading symbol getMyClass()\n"); - return 1; - } - - getMyClass = cast(getMyClass_fp) fp; - c = (*getMyClass)(); - foo(c); - - if (!Runtime.unloadLibrary(h)) - { printf("error freeing mydll.dll\n"); - return 1; - } - - printf("End...\n"); - return 0; - } -} -else -{ // static link the DLL - extern (C) - { - void* gc_getProxy(); - } - - int main() - { - printf("Start Static Link...\n"); - MyDLL_Initialize(gc_getProxy()); - 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; -} -------------------------------- - - $(P Let's start with the statically linked version, which is simpler. - It's compiled and linked with the command: - ) - -$(CONSOLE -C:>dmd test mydll.lib -g -) - - $(P Note how it is linked with $(TT mydll.lib), the import library - for $(TT mydll.dll). - The code is straightforward, it initializes $(TT mydll.lib) with - a call to $(B MyDLL_Initialize)(), passing the handle - to $(TT test.exe)'s gc. - Then, we can use the DLL and call its functions just as if - it were part of $(TT test.exe). In $(B foo)(), gc memory - is allocated and freed both by $(TT test.exe) and $(TT mydll.dll). - When we're done using the DLL, it is terminated with - $(B MyDLL_Terminate)(). - ) - - $(P Running it looks like this:) - -$(CONSOLE -C:>test -DLL_PROCESS_ATTACH -Start Static Link... -MyDLL_Initialize() -static this for mydll -Hello world! -MyDLL_Terminate() -static ~this for mydll -End... -C:> -) - - $(P The dynamically linked version is a little harder to set up. - Compile and link it with the command: - ) - -$(CONSOLE -C:>dmd test -version=DYNAMIC_LOAD -g -) - $(P The import library $(TT mydll.lib) is not needed. - The DLL is loaded with a call to - $(B Runtime.loadLibrary)(), - and each exported function has to be retrieved via - a call to - $(B GetProcAddress)(). - An easy way to get the decorated name to pass to $(B GetProcAddress)() - is to copy and paste it from the generated $(TT mydll.map) file - under the $(B Export) heading. - Once this is done, we can use the member functions of the - DLL classes as if they were part of $(TT test.exe). - When done, release the DLL with - $(B Runtime.unloadLibrary)(). - ) - - $(P Running it looks like this:) - -$(CONSOLE -C:>test -Start Dynamic Link... -DLL_PROCESS_ATTACH -static this for mydll -Hello world! -static ~this for mydll -DLL_PROCESS_DETACH -End... -C:> -) - -) - -Macros: - TITLE=Writing Win32 DLLs - WIKI=DLLs - CATEGORY_HOWTOS=$0 diff --git a/dmd.dd b/dmd.dd new file mode 100644 index 0000000000..90ecf0e6c3 --- /dev/null +++ b/dmd.dd @@ -0,0 +1,12 @@ +Ddoc + +$(D_S dmd - DMD Compiler, + +$(P Documentation for DMD is split up by operating system. Choose one from +the menu on the left.) + +) + +Macros: + TITLE=DMD Compiler + SUBNAV=$(SUBNAV_CLI_REFERENCE) diff --git a/doc.ddoc b/doc.ddoc index 6fca7c0cd0..2f2d9ff9fa 100644 --- a/doc.ddoc +++ b/doc.ddoc @@ -1,465 +1,23 @@ -DDOC= - - +ROOT_DIR = +ROOT = . +SELF_PATH = +BODYCLASS = doc +PROJECT = dlang.org +_= - +D_S = $(LAYOUT ,$1,$(ARGS $+)) +SPEC_S = $(LAYOUT ,$1,$(ARGS $+)) +COMMUNITY= $(LAYOUT ,$1,$(ARGS $+)) +_= - - - - -
- D Programming Language
- -
- - -GOOGLE_REFERRAL= - -COPYRIGHT= -Copyright © 1999-$(YEAR) by Digital Mars ®, All Rights Reserved - -FOOTER= - -
$(TITLE)
- $3 - $(GOOGLE_FOOTER) -$0
-TOCHEADERL =$3
-TOCENTRY = $(LI $(LINK2 $1, $2)) -TOCENTRYT = $(LI $3) -TOCENTRYH = $(LI $(LINK2 $1, $2)$3) -TOCENTRYTH = $(LI $3$4) - -ARGS=$0 -RPAREN = ) -LPAREN = ( -TABLE1 =-BLOCKQUOTE_PLAIN =$+
$1
-TT=$0 -SUB=$0 -LNAME2=$+ -SECTION1=$0
$1
$+ -SECTION2=$1
$+ -SECTION3=$1
$+ -SECTION4=$1
$+ -SINGLEQUOTE= ‘$0’ -DOUBLEQUOTE= “$0” - -NOTRANSLATE=$0
-NOTRANSLATE=$0
-D_CODE = $(NOTRANSLATE $0)-D_COMMENT = $0 -D_STRING = $0 -D_KEYWORD = $0 -D_PSYMBOL = $0 -D_PARAM = $0 - -D = $(NOTRANSLATE $0) -CODE=$(D $0) -CCODE=
$(NOTRANSLATE $0)-CPPCODE=
$(NOTRANSLATE $0)-GRAMMAR=
$(NOTRANSLATE $0)-DDOCCODE=
$(NOTRANSLATE $0)-SCINI=
$(NOTRANSLATE $0)-CONSOLE=
$(NOTRANSLATE $0)-MODDEFFILE=
$(NOTRANSLATE $0)- -MDASH=
-SEARCHIMG=
-DOWNLOADIMG=
-WIKIIMG=
-DIMG=
-NEWSIMG=
-OBJ2ASM=$(LINK2 http://digitalmars.com/ctg/obj2asm.html, obj2asm)
-DUMPOBJ=$(LINK2 http://digitalmars.com/ctg/dumpobj.html, dumpobj)
-SHELL=$(LINK2 http://digitalmars.com/ctg/shell.html, shell)
-PHOBOSSRC=$(LINK2 https://github.com/D-Programming-Language/phobos/blob/master/$0, $0)
-DRUNTIMESRC=$(LINK2 https://github.com/D-Programming-Language/druntime/blob/master/src/$0, $0)
-SAMPLESRC=$(LINK2 https://github.com/D-Programming-Language/dmd/blob/master/samples/$0, /dmd/samples/d/$0)
-DOLLAR=$
-
-AMAZON=
-AMAZONLINK= $(LINK2 http://www.amazon.com/exec/obidos/ASIN/$1/classicempire, $+)
-
-FOO=FOO
+AMAZONLINK= $(HTTP amazon.com/exec/obidos/ASIN/$1/classicempire, $+)
+_=
+MIDRULE=
+_=
diff --git a/documentation.dd b/documentation.dd
new file mode 100644
index 0000000000..0664ea3e9d
--- /dev/null
+++ b/documentation.dd
@@ -0,0 +1,6 @@
+Ddoc
+
+$(D_S Documentation, $(NAVIGATION_DOCUMENTATION))
+
+Macros:
+ TITLE=Documentation
diff --git a/download.dd b/download.dd
index c3f7b2f412..b930aac220 100644
--- a/download.dd
+++ b/download.dd
@@ -2,324 +2,325 @@ Ddoc
$(D_S Downloads,
-$(TABLE2 DMD - Digital Mars D Programming Language version 2,
-
- $(TR
- $(TH Download)
- $(TH Version)
- $(TH CPU)
- $(TH Operating System)
- $(TH Product)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd.$(DMDV2).zip)
- $(TD $(DMDV2))
- $(TD --)
- $(TDL $(WIN32) $(LINUX) $(OSX) $(FREEBSD))
- $(TD dmd D 2.0 compiler, all platforms)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd Windows installer)
- $(TD $(DMDV2))
- $(TD i386)
- $(TD $(WIN32))
- $(TD dmd D 2.0 compiler 1-click install for Windows)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd OSX installer (dmg))
- $(TD $(DMDV2))
- $(TD x86_64)
- $(TD $(OSX))
- $(TD dmd D 2.0 compiler .dmg installer for OSX)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(UBUNTU32_2))
- $(TD $(DEBV2))
- $(TD i386)
- $(TD $(UBUNTU))
- $(TD dmd D 2.0 compiler 1-click install for Ubuntu)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(UBUNTU64_2))
- $(TD $(DEBV2))
- $(TD x86_64)
- $(TD $(UBUNTU))
- $(TD dmd D 2.0 compiler 1-click install for Ubuntu)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(FEDORA32_2))
- $(TD $(RPMV2))
- $(TD i386)
- $(TD $(FEDORA))
- $(TD dmd D 2.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(FEDORA64_2))
- $(TD $(RPMV2))
- $(TD x86_64)
- $(TD $(FEDORA))
- $(TD dmd D 2.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(OPENSUSE32_2))
- $(TD $(RPMV2))
- $(TD i386)
- $(TD $(OPENSUSE))
- $(TD dmd D 2.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(OPENSUSE64_2))
- $(TD $(RPMV2))
- $(TD x86_64)
- $(TD $(OPENSUSE))
- $(TD dmd D 2.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(LINK2 changelog.html, 2.0 changelog))
- $(TD all)
- $(TD )
- $(TD )
- $(TD other dmd 2.0 versions)
- )
-)
-$(BR)
-$(BR)
-
-$(TABLE2 DMD - Digital Mars D Programming Language version 1 (please note: D1 will be discontinued effective December 31, 2012),
- $(TR
- $(TH Download)
- $(TH Version)
- $(TH CPU)
- $(TH Operating System(s))
- $(TH Product)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd.$(DMDV1).zip)
- $(TD $(DMDV1))
- $(TD --)
- $(TDL $(WIN32) $(LINUX) $(OSX) $(FREEBSD))
- $(TD dmd D 1.0 compiler, all platforms)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd Windows installer)
- $(TD $(DMDV1))
- $(TD i386)
- $(TD $(WIN32))
- $(TD dmd D 1.0 compiler 1-click install for Windows)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd OSX installer (dmg))
- $(TD $(DMDV1))
- $(TD x86_64)
- $(TD $(OSX))
- $(TD dmd D 1.0 compiler .dmg installer for OSX)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(UBUNTU32_1))
- $(TD $(DEBV1))
- $(TD i386)
- $(TD $(UBUNTU))
- $(TD dmd D 1.0 compiler 1-click install for Ubuntu)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(UBUNTU64_1))
- $(TD $(DEBV1))
- $(TD x86_64)
- $(TD $(UBUNTU))
- $(TD dmd D 1.0 compiler 1-click install for Ubuntu)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(FEDORA32_1))
- $(TD $(RPMV1))
- $(TD i386)
- $(TD $(FEDORA))
- $(TD dmd D 1.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(FEDORA64_1))
- $(TD $(RPMV1))
- $(TD x86_64)
- $(TD $(FEDORA))
- $(TD dmd D 1.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(OPENSUSE32_1))
- $(TD $(RPMV1))
- $(TD i386)
- $(TD $(OPENSUSE))
- $(TD dmd D 1.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) $(OPENSUSE64_1))
- $(TD $(RPMV1))
- $(TD x86_64)
- $(TD $(OPENSUSE))
- $(TD dmd D 1.0 compiler 1-click install as rpm)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmd.1.030.zip)
- $(TD 1.030)
- $(TD i386)
- $(TD $(WIN32) $(LINUX))
- $(TD dmd D 1.0 compiler)
- )
-
- $(TRCOMMENT
- $(TD $(DOWNLOADIMG) dmd 1.030 bundle)
- $(TD 1.030)
- $(TD i386)
- $(TD $(WIN32))
- $(TD dmd D 1.0 compiler bundled with various libraries)
- )
-
- $(TR
- $(TD $(LINK2 http://digitalmars.com/d/1.0/changelog.html, 1.0 changelog))
- $(TD all)
- $(TD )
- $(TD )
- $(TD other dmd 1.0 versions)
- )
+$(DIVC download-tables,
+
+$(TABLEC download-compilers,
+ $(T caption,
+ $(DIVID download-choose, ($(LINK2 https://wiki.dlang.org/Compilers, more information)))
+ $(H2 Choose a compiler)
+ )
+ $(TR
+ $(TD $(LINK2 #dmd, $(IMG compiler-dmd.png)))
+ $(TD $(LINK2 https://gdcproject.org/downloads, $(IMG compiler-gdc.svg)))
+ $(TD $(LINK2 https://github.com/ldc-developers/ldc#installation, $(IMG compiler-ldc.png)))
+ )
+ $(TR
+ $(TD
+ $(H3 DMD)
+ $(UL
+ $(LI Official reference compiler)
+ $(LI Latest D version)
+ $(LI Simple installation)
+ $(LI Very fast compilation speeds)
+ $(LI Architectures: i386, amd64)
+ )
+ )
+ $(TD
+ $(H3 GDC)
+ $(UL
+ $(LI $(LINK2 https://gcc.gnu.org/, GCC)-based D compiler)
+ $(LI Strong optimization)
+ $(LI Great $(LINK2 https://www.gnu.org/software/gdb/,GDB) support)
+ $(LI Architectures: i386, amd64, x32, armel, armhf, $(LINK2 https://wiki.dlang.org/Compilers#Comparison,others))
+ )
+ )
+ $(TD
+ $(H3 LDC)
+ $(UL
+ $(LI $(LINK2 https://llvm.org/, LLVM)-based D compiler)
+ $(LI Strong optimization)
+ $(LI
+ $(LINK2 https://wiki.dlang.org/Build_D_for_Android, Android support)
+ )
+ $(LI Architectures: i386, amd64, armel, armhf, $(LINK2 https://wiki.dlang.org/Compilers#Comparison,others))
+ )
+ )
+ )
+ $(TR
+ $(TD
+ $(DIVC download-link, $(LINK2 dmd-windows.html, About) · $(LINK2 #dmd, Download))
+ )
+ $(TD
+ $(DIVC download-link, $(LINK2 https://gdcproject.org/, About) · $(LINK2 https://gdcproject.org/downloads, Download))
+ )
+ $(TD
+ $(DIVC download-link, $(LINK2 https://wiki.dlang.org/LDC, About) · $(LINK2 https://github.com/ldc-developers/ldc#installation, Download))
+ )
+ )
+ $(TR
+ $(DONATE_BUTTON)
+ )
)
-$(BR)
-$(BR)
-
-$(TABLE2 DMD - Digital Mars C and C++ Compiler,
- $(TR
- $(TH Download)
- $(TH Version)
- $(TH CPU)
- $(TH Operating System(s))
- $(TH Product)
- )
-
- $(TR
- $(TD $(DOWNLOADIMG) dmc.zip)
- $(TD 8.50)
- $(TD i386)
- $(TD $(WIN32))
- $(TD C++ Compiler and Utilities)
- )
+$(TABLEC lsp,
+ $(TR
+ $(TD $(LINK2 https://github.com/Pure-D/serve-d/#usage, $(IMG lsp-served-logo.png)))
+ )
+ $(TR
+ $(TD
+ $(H3 Language Server)
+ $(P
+ To start coding effectively, we recommend using an editor supporting the
+ Language Server Protocol. For $(B VSCode) you can immediately install the
+ $(LINK2 https://marketplace.visualstudio.com/items?itemName=webfreak.code-d, VSCode extension $(B code-d))
+ $(LINK2 https://open-vsx.org/extension/webfreak/code-d, [openvsx])
+ )
+ )
+ )
+ $(TR
+ $(TD
+ $(DIVC download-link, $(LINK2 https://github.com/Pure-D/serve-d/#usage, About) · $(LINK2 https://github.com/Pure-D/serve-d/releases, Download))
+ )
+ )
+)
)
-$(BR)
-$(BR)
-
- $(TABLE2 GDC - D Programming Language for GCC,
- $(TR
- $(TH Download)
- $(TH Operating System)
- $(TH Product)
- )
-
-
- $(TR
- $(TDXX $(LINK2 http://sourceforge.net/project/showfiles.php?group_id=154306, GDC))
- $(TD $(LINK2 http://bitbucket.org/goshawk/gdc/wiki/Home, GDC))
- $(TD all)
- $(TD GDC)
- )
-
- $(TR
- $(TD $(LINK2 http://sourceforge.net/projects/gdcmac, gdcmac))
- $(TD $(OSX))
- $(TD GDC)
- )
-
- $(TR
- $(TD $(D sudo apt-get install gdc))
- $(TD $(DEBIAN) $(UBUNTU))
- $(TD GDC)
- )
- )
-
-$(SECTION2 Documentation Downloads,
-
- $(UL
- $(LI $(LINK2 http://digitalmars.com/d/2.0/dlangspec.mobi, $(DOWNLOADIMG) D Programming Language Specification 2.0) ebook)
- $(LI $(LINK2 http://www.prowiki.org/upload/duser/spec_DMD_1.00.pdf, $(DOWNLOADIMG) DMD 1.0 pdf) English)
+$(DIVC download_channels,
+ $(DIVC download_channel,
+ $(H2 $(LNAME2 dmd,DMD $(DMDV2)))
+ $(LINK2 changelog/$(DMDV2).html, Changelog)
+
+ $(BR)$(BR)
+
+ $(DOWNLOAD Windows, $(WINDOWS), windows, Windows,
+ $(SBTN $(WINEXE), Installer) $(SBTN $(ARCH windows, 7z), 7z)
+ )
+
+ $(DOWNLOAD macOS, $(OSX), osx, macOS,
+ $(SBTN $(OSXDMG), dmg) $(SBTN $(ARCH osx, tar.xz), tar.xz)
+ )
+
+ $(MESSAGE_BOX orange, $(B Warning) -
+ MacOS 15.4 introduced an internal change causing D programs to crash on startup ($(LINK2 https://github.com/dlang/dmd/issues/21126, Issue 21126)), including DMD 2.111 itself.
+ Please use a $(LINK2 https://github.com/dlang/dmd/releases/download/nightly/dmd.master.osx.tar.xz, nightly release) until 2.112 releases.
+ )
+
+ $(BR)
+
+ $(DOWNLOAD Ubuntu/Debian, $(UBUNTU) $(DEBIAN), linux, Linux,
+ $(SBTN $(DEB32), i386) $(SBTN $(DEB64), x86_64) $(SBTN $(ARCH linux, tar.xz), tar.xz)
+ )
+
+ $(DOWNLOAD Fedora/CentOS, $(FEDORA) $(CENTOS), linux, Linux,
+ $(SBTN $(RPM32), i386) $(SBTN $(RPM64), x86_64) $(SBTN $(ARCH linux, tar.xz), tar.xz)
+ )
+
+ $(DOWNLOAD openSUSE, $(OPENSUSE), linux, Linux,
+ $(SBTN $(SUSE32), i386) $(SBTN $(SUSE64), x86_64) $(SBTN $(ARCH linux, tar.xz), tar.xz)
+ )
+
+ $(DOWNLOAD FreeBSD, $(FREEBSD), freebsd, FreeBSD,
+ $(SBTN $(ARCH freebsd-64, tar.xz), x86_64)
+ )
+
+ $(INSTALL_SCRIPT curl -fsS https://dlang.org/install.sh | bash -s dmd)
+ )
+
+ $(BETA
+ $(DIVC download_channel,
+ $(H2 $(LNAME2 dmd_beta,DMD Beta $(B_DMDV2)-$(B_SUFFIX)))
+ $(LINK2 changelog/$(B_DMDV2).html, Changelog)
+
+ $(BR)$(BR)
+
+ $(DOWNLOAD Windows, $(WINDOWS), windows, Windows,
+ $(SBTN $(B_WINEXE), exe) $(SBTN $(B_ARCH windows, 7z), 7z)
+ )
+
+ $(DOWNLOAD macOS, $(OSX), osx, macOS,
+ $(SBTN $(B_OSXDMG), dmg) $(SBTN $(B_ARCH osx, tar.xz), tar.xz)
+ )
+
+ $(DOWNLOAD Ubuntu/Debian, $(UBUNTU) $(DEBIAN), linux, Linux,
+ $(SBTN $(B_DEB32), i386) $(SBTN $(B_DEB64), x86_64) $(SBTN $(B_ARCH linux, tar.xz), tar.xz)
+ )
+
+ $(DOWNLOAD Fedora/CentOS, $(FEDORA) $(CENTOS), linux, Linux,
+ $(SBTN $(B_RPM32), i386) $(SBTN $(B_RPM64), x86_64) $(SBTN $(B_ARCH linux, tar.xz), tar.xz)
+ )
+
+ $(DOWNLOAD openSUSE, $(OPENSUSE), linux, Linux,
+ $(SBTN $(B_SUSE32), i386) $(SBTN $(B_SUSE64), x86_64) $(SBTN $(B_ARCH linux, tar.xz), tar.xz)
)
-)
-$(SECTION2 Other Downloads,
- $(UL
- $(LI $(LINK2 http://www.digitalmars.com/download/freecompiler.html,
- C and C++ compiler downloads)
- )
-
- $(LI
-
- $(DOWNLOADIMG) DMDScript source
- )
-
- $(LI
-
- $(DOWNLOADIMG) Empire 2.01 source
- )
+ $(DOWNLOAD FreeBSD, $(FREEBSD), freebsd, FreeBSD,
+ $(SBTN $(B_ARCH freebsd-64, tar.xz), x86_64)
)
+
+ $(INSTALL_SCRIPT curl -fsS https://dlang.org/install.sh | bash -s dmd-beta)
+ )
+ )
+)
+
+$(H3
+ $(LINK2 https://downloads.dlang.org, Release Archive)
+)
+$(LINK2 gpg_keys.html, GPG keys)$(BR)
+$(LINK2 https://github.com/dlang/dmd/releases/tag/nightly, Nightly Builds)$(BR)
+$(LINK2 https://github.com/dlang, D on GitHub)
+
+$(HR)
+
+$(H2 Third-party downloads)
+
+These links are not maintained by the same people maintaining the official downloads.
+$(BR)$(BR)
+
+$(DOWNLOAD_OTHER $(ARCHLINUX), $(LINK2 https://wiki.archlinux.org/index.php/D_(programming_language), Arch Linux), $(CONSOLE pacman -S dlang))
+
+$(DOWNLOAD_OTHER $(GENTOO), $(LINK2 https://wiki.gentoo.org/wiki/Dlang, Gentoo), $(CONSOLE eselect repository enable dlang))
+
+$(DOWNLOAD_OTHER $(HOMEBREW), $(LINK2 https://formulae.brew.sh/formula/dmd, Homebrew), $(CONSOLE brew install dmd))
+
+$(DOWNLOAD_OTHER $(NIX), $(LINK2 https://search.nixos.org/packages?show=dmd&query=dmd, Nix/NixOS), $(CONSOLE nix-env -iA nixpkgs.dmd)
+$(LINK2 https://github.com/petarkirov/dlang.nix, derivations for various compiler versions)
)
+$(DOWNLOAD_OTHER $(UBUNTU) $(DEBIAN), Ubuntu/Debian, $(LINK2 https://d-apt.sourceforge.net/, APT repository)
+$(CONSOLE sudo wget https://netcologne.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list
+sudo apt-get update --allow-insecure-repositories
+sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring
+sudo apt-get update && sudo apt-get install dmd-compiler dub)
+)
+
+$(DOWNLOAD_OTHER $(DOCKER), $(LINK2 https://hub.docker.com/r/dlang2/dmd-ubuntu, Docker), $(CONSOLE docker run --rm -ti -v $(DOLLAR)(pwd):/src dlang2/dmd-ubuntu dmd))
+
+$(DOWNLOAD_OTHER $(OPENSUSE), $(LINK2 https://build.opensuse.org/package/show/devel:languages:D/dmd, OpenSUSE Tumbleweed), $(CONSOLE sudo zypper install dmd))
+
+$(DOWNLOAD_OTHER $(SNAP), $(LINK2 https://snapcraft.io/dmd, Snap),
+ $(CONSOLE # install DMD compiler (including RDMD)
+sudo snap install --classic dmd
+
+\# install DUB package/build manager
+sudo snap install --classic dub
+
+\# install LDC compiler with LLVM backend
+sudo snap install --classic ldc2))
+
+$(DOWNLOAD_OTHER $(OPENBSD), $(LINK2 https://openports.pl/path/lang/dmd, OpenBSD), $(CONSOLE # install DMD compiler
+doas pkg_add dmd
+
+\# install DUB package/build manager (and DMD if not already installed)
+doas pkg_add dub
+
+\# install D tools
+doas pkg_add dtools))
+
+$(H2 Other Downloads)
+
+$(UL
+$(LI $(LINK2 https://github.com/dlang/visuald/releases, VisualD - D Plugin for Visual Studio))
+
+$(LI $(LINK2 https://dlang.org/spec/spec.html, D Programming Language Specification): $(BTN https://dlang.org/dlangspec.mobi, mobi))
+
+$(LI $(LINK2 https://www.digitalmars.com/download/freecompiler.html, Digital Mars C and C++ Compiler Downloads))
+)
)
Macros:
- TITLE=Downloads
- WIKI=Downloads
- DMDV1=1.072
- DMDV2=2.057
- DEBV1=1.072
- DEBV2=2.057
- RPMV1=1.072
- RPMV2=2.057
-
- OPENSUSE64_1=dmd-1.072-0.openSUSE.x86_64.rpm
- OPENSUSE64_2=dmd-2.057-0.openSUSE.x86_64.rpm
- OPENSUSE32_1=dmd-1.072-0.openSUSE.i386.rpm
- OPENSUSE32_2=dmd-2.057-0.openSUSE.i386.rpm
-
- FEDORA64_1=dmd-1.072-0.fedora.x86_64.rpm
- FEDORA64_2=dmd-2.057-0.fedora.x86_64.rpm
- FEDORA32_1=dmd-1.072-0.fedora.i386.rpm
- FEDORA32_2=dmd-2.057-0.fedora.i386.rpm
-
- UBUNTU64_1=dmd_$(DEBV1)-0_amd64.deb
- UBUNTU64_2=dmd_$(DEBV2)-0_amd64.deb
- UBUNTU32_1=dmd_$(DEBV1)-0_i386.deb
- UBUNTU32_2=dmd_$(DEBV2)-0_i386.deb
-
- LOGO=
+ CENTOS=$(LOGO centos, CentOS)
+ DEBIAN=$(LOGO debian, Debian)
+ DOCKER=$(LOGO docker, Docker)
+ FEDORA=$(LOGO fedora, Fedora)
+ FREEBSD=$(LOGO freebsd, FreeBSD 8.1)
+ LINUX=$(LOGO linux, Linux)
+ OPENSUSE=$(LOGO opensuse, OpenSUSE)
+ OSX=$(LOGO apple, OSX Lion)
+ UBUNTU=$(LOGO ubuntu, Ubuntu)
+ ARCHLINUX=$(LOGO archlinux, Arch Linux)
+ GENTOO=$(LOGO gentoo, Gentoo)
+ HOMEBREW=$(LOGO homebrew, Homebrew)
+ NIX=$(LOGO nix, Nix/NixOS)
+ SNAP=$(LOGO snapcraft, Snap)
+ WINDOWS=$(LOGO windows, Windows)
+ OPENBSD=$(LOGO openbsd, OpenBSD)
+
+ LINK_OS=$2
+
+ SBTN=$(SPANC sig_btn,$(BTN $1,$+)$(BTN $1.sig,sig)) + BTN=$+ + H3I=
$0
+ DLSITE=https://downloads.dlang.org/releases/2.x/$(DMDV2)/$0 + B_DLSITE=https://downloads.dlang.org/pre-releases/2.x/$(B_DMDV2)/$0 + DOWNLOAD = + $(DIV, + $(DIVC download_image, $2) + $(DIVC download_paragraph, +$1
+ + $(LINK_OS $3, , $4) + +Install Script
+ + $(LINK2 $(ROOT_DIR)install.html, ) + + $(PRE $(CODE $1))) + CONSOLE=$(PRE $(CODE $1)) + IMG=#{info.mod.qualifiedName}.#{title[0 .. $-24]} #{title[$-24 ..$]}
+ - else if (hidx > 0 && !title.startsWith("Module ") && node)
+ h1 #{title[0 .. hidx]} #{node.parent.qualifiedName}.#{node.name}
+ - else if (hidx > 0 && title.startsWith("Module ") && info.mod)
+ h1 Module #{info.mod.qualifiedName}
+ - else
+ h1= title
+ block body
+
+ |
+ #quickindex.quickindex
+
+ #copyright.smallprint
+ | Copyright © 1999-#{year} by the D Language Foundation | Page generated by ddox.
+
+ script(type='text/javascript', src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js')
+ |
+ script(type='text/javascript').
+ window.jQuery || document.write('\x3Cscript src="#{root_dir}js/jquery-1.7.2.min.js">\x3C/script>')
+ |
+ script(type='text/javascript', src='#{root_dir}js/codemirror-compressed.js')
+ |
+ script(type='text/javascript', src='#{root_dir}js/run.js')
+ script(type='text/javascript', src='#{root_dir}js/run_examples.js')
+ script(type='text/javascript', src='#{root_dir}js/dlang.js')
+ script(type='text/javascript', src='#{root_dir}js/listanchors.js')
+ script(type="text/javascript", src="#{root_dir}js/ddox.js")
+ script(type='text/javascript').
+ jQuery(document).ready(listanchors);
+ setupDdox();
diff --git a/dpl_latest_htaccess b/dpl_latest_htaccess
new file mode 100644
index 0000000000..520eff7938
--- /dev/null
+++ b/dpl_latest_htaccess
@@ -0,0 +1,7 @@
+# Enable mod_rewrite
+RewriteEngine On
+RewriteBase /library/
+
+# rewrite any URL in dpl_rewrite_map
+RewriteCond ${dpl_rewrite_map:%{REQUEST_URI}|NOT_FOUND} !NOT_FOUND
+RewriteRule ^ ${dpl_rewrite_map:%{REQUEST_URI}} [R=301,L]
diff --git a/dpl_prerelease_htaccess b/dpl_prerelease_htaccess
new file mode 100644
index 0000000000..b531566451
--- /dev/null
+++ b/dpl_prerelease_htaccess
@@ -0,0 +1,7 @@
+# Enable mod_rewrite
+RewriteEngine On
+RewriteBase /library-prerelease/
+
+# rewrite any URL in dpl_rewrite_map
+RewriteCond ${dpl_rewrite_map:%{REQUEST_URI}|NOT_FOUND} !NOT_FOUND
+RewriteRule ^ ${dpl_rewrite_map:%{REQUEST_URI}} [R=301,L]
diff --git a/dstyle.dd b/dstyle.dd
index d5fedb284a..0527eaac4b 100644
--- a/dstyle.dd
+++ b/dstyle.dd
@@ -2,230 +2,509 @@ Ddoc
$(D_S The D Style,
+
+
$(P
- $(I 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
- code and easier for you to work with others' code.
- The D Style can form the starting point for a project
- style guide customized for your project team.
+ $(I 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
+ code and easier for you to work with others' code.
+ The D Style can form the starting point for a project
+ style guide customized for your project team.
)
$(P
- Submissions to Phobos and other official D source code will
- follow these guidelines.
+ Submissions to Phobos and other official D source code will
+ follow these guidelines.
)
-
+
$(P $(I by Jonathan M Davis))
$(H2 Introduction)
@@ -35,7 +37,7 @@ $(D_S $(TITLE),
$(P $(STD_DATETIME), on the other hand, is very much an object-oriented
solution, and it's not C-based at all. Rather, its API is based on
- $(WEB www.boost.org/doc/libs/release/doc/html/date_time.html, Boost)'s
+ $(HTTP www.boost.org/doc/libs/release/doc/html/date_time.html, Boost)'s
types for handling dates and times (though they're far from identical).
So, it's a bit of a paradigm shift to move from $(STD_DATE) to
$(STD_DATETIME). Don't expect much to be the same between the two.
@@ -64,9 +66,9 @@ $(D_S $(TITLE),
$(P The duration types can actually be found in $(CORE_TIME). They are
$(DURATION) and $(TICK_DURATION). $(TICK_DURATION) is intended for
- precision timing and is used primarily with $(XREF datetime, StopWatch)
+ precision timing and is used primarily with $(REF_SHORT StopWatch, std,datetime)
and the benchmarking functions found in $(STD_DATETIME) - such as
- $(XREF datetime, benchmark) - and you're unlikely to use it outside of
+ $(REF_SHORT benchmark, std,datetime) - and you're unlikely to use it outside of
using them. $(DURATION), on the other hand, you're likely to use quite a
bit.)
@@ -78,7 +80,7 @@ $(D_S $(TITLE),
(the $(D total) function).)
$(P Generally, a $(DURATION) is created in one of two ways: by subtracting
- two time points or with the $(FULL_CXREF time, dur) function. So, for
+ two time points or with the $(REF dur, core,time) function. So, for
instance, if you subtracted a time point which represented 17:02 from
a time point which represented 6:07, you'd get a $(DURATION) which
represented 10 hours and 55 minutes. Or, if you wanted to create a
@@ -102,8 +104,8 @@ assert(duration.total!"hnsecs"() == 393_000_000_000);
Phobos which take a duration of time take an actual $(DURATION) rather
than a naked number (most currently take both, though the versions which
take a naked number are going to be deprecated). For instance,
- $(FULL_CXREF thread, sleep) takes a $(DURATION), as does
- $(FULL_XREF concurrency, receiveTimeout). So, durations are used outside
+ $(REF sleep, core,thread) takes a $(DURATION), as does
+ $(REF receiveTimeout, std,concurrency). So, durations are used outside
of just interacting with $(CORE_TIME) and $(STD_DATETIME).)
$(P One particular thing to note here is how both $(D dur) and $(D total)
@@ -115,7 +117,7 @@ assert(duration.total!"hnsecs"() == 393_000_000_000);
however that very few functions take $(D "nsecs"), because nothing in
$(STD_DATETIME), and very little in $(CORE_TIME), has precision
greater than hnsecs (100 ns). Also, a number of functions (such as
- $(FULL_CXREF time, dur)) do not take $(D "years") or $(D "months"),
+ $(REF dur, core,time)) do not take $(D "years") or $(D "months"),
because it is not possible to convert between years or months and
smaller units without a specific date. So, while you can add a
$(DURATION) to a time point, if you want to add years or months to one,
@@ -170,13 +172,13 @@ assert(tod == dateTime.timeOfDay);
them, but you do risk problems with DST when creating a $(SYSTIME) from
the other 3 time points unless you specifically create the $(SYSTIME)
with a $(TIMEZONE) which doesn't have DST (such as
- $(FULL_XREF datetime, UTC)), since when a time zone has DST, one hour of
+ $(REF UTC, std,datetime)), since when a time zone has DST, one hour of
the year does not exist, and another exists twice. You can also convert
to and from unix time, which is what you're dealing with in C with
$(D time_t).)
$(P The one other related type which I should mention at this point is
- $(FULL_CXREF time, FracSec). It holds fractional seconds, and it is
+ $(REF FracSec, core,time). It holds fractional seconds, and it is
what you get from a $(DURATION) or $(SYSTIME) when you specifically
ask for the fractional portion of the time.)
@@ -234,7 +236,7 @@ assert(stdTime == st.stdTime);
C# uses, so if you need to interface with C# for any reason, converting
between its representation of time and $(STD_DATETIME)'s representation
is extremely easy, since no conversion is necessary.
- $(WEB msdn.microsoft.com/en-us/library/system.datetime.aspx,
+ $(HTTP msdn.microsoft.com/en-us/library/system.datetime.aspx,
C#'s $(D DateTime)) uses both the same units and epoch for its internal
representation (which it calls $(D Ticks)) as $(SYSTIME), though unlike
$(SYSTIME), it doesn't work with negative values (which would be B.C.)
@@ -253,7 +255,7 @@ assert(stdTime == st.stdTime);
at all or are dealing with anything which needs to worry about DST,
you should use $(SYSTIME). Because it keeps its time internally in UTC,
it avoids problems with DST. And while it does have a time zone
- component, it defaults to $(FULL_XREF datetime, LocalTime) (which
+ component, it defaults to $(REF LocalTime, std,datetime) (which
is the time zone type for the local time of the system), so you don't
generally have to deal directly with time zones if you don't want to.)
@@ -264,7 +266,7 @@ assert(stdTime == st.stdTime);
That's unlikely to be necessary, however (and if you think that you
have come up with such a class which would be generally useful, please
bring it up in the
- $(WEB www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup),
+ $(HTTP www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup),
since if it's truly generally useful, we may want some version of it in
$(STD_DATETIME)). Read their documentation for more details. Most
applications shouldn't have to worry about time zones though, beyond
@@ -499,8 +501,8 @@ setTimes("yourfile.txt", sysTime, sysTime + dur!"msecs"(5));
use as discussed previously (such as its std time or its ISO string),
or you're going to have be converting between $(D d_time) and
$(SYSTIME). At present, the functions
- $(FULL_XREF datetime, sysTimeToDTime) and
- $(FULL_XREF datetime, dTimeToSysTime) will do those conversions for you.
+ $(REF sysTimeToDTime, std,datetime) and
+ $(REF dTimeToSysTime, std,datetime) will do those conversions for you.
So, converting between the two formats is easy. However, because
$(D d_time) is going away, those functions will be going away. That
means that you either need to refactor your code so that those functions
@@ -538,8 +540,8 @@ setTimes("yourfile.txt", sysTime, sysTime + dur!"msecs"(5));
Simply calculate the total UTC offset (so add in the DST offset if
it applies for the date in question) in minutes and create a $(SIMPLETZ)
with that. Note that $(STD_DATETIME) treats west of UTC as
- $(I negative) (for some reason, some systems - particularly Posix stuff
- - use a positive offset from UTC when west of UTC, in spite of the fact
+ $(I negative) (for some reason, some systems - particularly Posix stuff -
+ use a positive offset from UTC when west of UTC, in spite of the fact
that when talking about time zones, negative is always used for west of
UTC, and that's what the ISO standard strings do). So, you may have to
adjust your values accordingly. Regardless, be very careful to make
@@ -560,20 +562,20 @@ immutable tzWithoutDST = new SimpleTimeZone(utcOffset);
$(P The last thing that I have to note is some differences in numerical
values between $(STD_DATE) and $(STD_DATETIME).
- $(FULL_XREF date, Date)'s $(D weekday) property gives Sunday a value of
- 1, but $(FULL_XREF date, weekDay) gives Sunday a value of 0.
- $(FULL_XREF datetime, DayOfWeek) gives Sunday a value of 0. So,
+ $(D std.date.Date)'s $(D weekday) property gives Sunday a value of
+ 1, but $(D std.date.weekDay) gives Sunday a value of 0.
+ $(REF DayOfWeek, std,datetime) gives Sunday a value of 0. So,
depending on which part of $(STD_DATE) you're dealing with it, it
may or may not match what $(STD_DATETIME) is doing for the numerical
values of weekdays. Months have a similar problem.
- $(FULL_XREF date, Date)'s $(D month) property gives January a value of
- 1 - which matches what $(FULL_XREF datetime, Month) does - but
- $(FULL_XREF date, monthFromTime) gives January a value of 0. So,
+ $(D std.date.Date)'s $(D month) property gives January a value of
+ 1 - which matches what $(REF Month, std,datetime) does - but
+ $(D std.date.monthFromTime) gives January a value of 0. So,
just as with the days of the week, you have to be careful with the
numerical values of the months. Whether $(STD_DATETIME) matches what
$(STD_DATE) is doing depends on which part of $(STD_DATE) you're using.
And as you'll notice, it's not even consistent as to whether
- $(FULL_XREF date, Date) or the free function in $(STD_DATE) is the one
+ $(D std.date.Date) or the free function in $(STD_DATE) is the one
which matches $(STD_DATETIME). So, you should be very careful when
converting code which uses numerical values for either the days of the
week or the months of the year.)
@@ -581,9 +583,9 @@ immutable tzWithoutDST = new SimpleTimeZone(utcOffset);
$(BOOKTABLE $(H3 std.date symbols and their std.datetime counterparts),
$(TR $(TD $(B $(STD_DATE)))
$(TD $(B $(STD_DATETIME) Equivalent)))
- $(TR $(TD $(XREF date, d_time))
+ $(TR $(TD $(D d_time))
$(TD The closest would be $(SYSTIME).))
- $(TR $(TD $(XREF date, d_time_nan))
+ $(TR $(TD $(D d_time_nan))
$(TD There is no equivalent. $(SYSTIME).$(D init), which has a
$(D null) $(TIMEZONE) object, would be the closest, but once
CTFE advances to the point that you can new up class objects
@@ -592,26 +594,26 @@ immutable tzWithoutDST = new SimpleTimeZone(utcOffset);
invalid. $(STD_DATETIME) in general tries to avoid having any
invalid states for any of its types. It's intended that
creating such values be impossible.))
- $(TR $(TD $(XREF date, Date))
+ $(TR $(TD $(D Date))
$(TD $(SYSTIME)))
- $(TR $(TD $(XREF date, Date).$(D year))
+ $(TR $(TD $(D Date).$(D year))
$(TD $(SYSTIME).$(D year)))
- $(TR $(TD $(XREF date, Date).$(D month))
+ $(TR $(TD $(D Date).$(D month))
$(TD $(SYSTIME).$(D month)))
- $(TR $(TD $(XREF date, Date).$(D day))
+ $(TR $(TD $(D Date).$(D day))
$(TD $(SYSTIME).$(D day)))
- $(TR $(TD $(XREF date, Date).$(D hour))
+ $(TR $(TD $(D Date).$(D hour))
$(TD $(SYSTIME).$(D hour)))
- $(TR $(TD $(XREF date, Date).$(D minute))
+ $(TR $(TD $(D Date).$(D minute))
$(TD $(SYSTIME).$(D minute)))
- $(TR $(TD $(XREF date, Date).$(D second))
+ $(TR $(TD $(D Date).$(D second))
$(TD $(SYSTIME).$(D second)))
- $(TR $(TD $(XREF date, Date).$(D ms))
+ $(TR $(TD $(D Date).$(D ms))
$(TD $(SYSTIME).$(D fracSec.msecs)))
- $(TR $(TD $(XREF date, Date).$(D weekday))
+ $(TR $(TD $(D Date).$(D weekday))
$(TD $(SYSTIME).$(D dayOfWeek) - but note that the values are off
by 1.))
- $(TR $(TD $(XREF date, Date).$(D tzcorrection))
+ $(TR $(TD $(D Date).$(D tzcorrection))
$(TD
--------------------
immutable tz = sysTime.timezone;
@@ -621,40 +623,40 @@ auto tzcorrection = convert!("hnsecs", "minutes")(diff);
However, it looks like $(D tzcorrection) is broken, so you're probably not using
it in your code anyway.
))
- $(TR $(TD $(XREF date, Date).$(D parse))
+ $(TR $(TD $(D Date).$(D parse))
$(TD $(SYSTIME).$(D fromISOString),
$(SYSTIME).$(D fromISOExtString), and
$(SYSTIME).$(D fromSimpleString), but the formats of the
- strings differ from what $(FULL_XREF date, Date).$(D parse)
+ strings differ from what $(D std.date.Date).$(D parse)
accepts.))
- $(TR $(TD $(XREF date, ticksPerSecond))
+ $(TR $(TD $(D ticksPerSecond))
$(TD There is no equivalent. It's only relevant to $(D d_time).))
- $(TR $(TD $(XREF date, toISO8601YearWeek))
+ $(TR $(TD $(D toISO8601YearWeek))
$(TD $(SYSTIME).$(D isoWeek)))
- $(TR $(TD $(XREF date, hourFromTime))
+ $(TR $(TD $(D hourFromTime))
$(TD $(SYSTIME).$(D hour)))
- $(TR $(TD $(XREF date, minFromTime))
+ $(TR $(TD $(D minFromTime))
$(TD $(SYSTIME).$(D minute)))
- $(TR $(TD $(XREF date, secFromTime))
+ $(TR $(TD $(D secFromTime))
$(TD $(SYSTIME).$(D second)))
- $(TR $(TD $(XREF date, daysInYear))
+ $(TR $(TD $(D daysInYear))
$(TD $(D sysTime.isLeapYear ? 366 : 365)))
- $(TR $(TD $(XREF date, dayFromYear))
+ $(TR $(TD $(D dayFromYear))
$(TD $(D (sysTime - SysTime(Date(1970, 1, 1), UTC())).total!"days"())))
- $(TR $(TD $(XREF date, yearFromTime))
+ $(TR $(TD $(D yearFromTime))
$(TD $(SYSTIME).$(D year)))
- $(TR $(TD $(XREF date, inLeapYear))
+ $(TR $(TD $(D inLeapYear))
$(TD $(SYSTIME).$(D isLeapYear)))
- $(TR $(TD $(XREF date, monthFromTime))
+ $(TR $(TD $(D monthFromTime))
$(TD $(SYSTIME).$(D month) - but note that the values are off by
1.))
- $(TR $(TD $(XREF date, dateFromTime))
+ $(TR $(TD $(D dateFromTime))
$(TD $(SYSTIME).$(D day)))
- $(TR $(TD $(XREF date, weekDay))
+ $(TR $(TD $(D weekDay))
$(TD $(SYSTIME).$(D dayOfWeek)))
- $(TR $(TD $(XREF date, UTCtoLocalTime))
+ $(TR $(TD $(D UTCtoLocalTime))
$(TD $(SYSTIME).$(D toUTC)))
- $(TR $(TD $(XREF date, dateFromNthWeekdayOfMonth))
+ $(TR $(TD $(D dateFromNthWeekdayOfMonth))
$(TD
--------------------
//There is no equivalent. This is a possible implementation.
@@ -665,9 +667,9 @@ int dateFromNthWeekdayOfMonth(int year, Month month,
auto target = first;
immutable targetDOTW = target.dayOfWeek;
- if(targetDOTW != dow)
+ if (targetDOTW != dow)
{
- if(targetDOTW < dow)
+ if (targetDOTW < dow)
target += dur!"days"(dow - targetDOTW);
else
{
@@ -678,60 +680,60 @@ int dateFromNthWeekdayOfMonth(int year, Month month,
target += dur!"weeks"(n - 1);
- if(target.month != first.month)
+ if (target.month != first.month)
target -= dur!"weeks"(1);
return cast(int)((target - first).total!"days"()) + 1;
}
--------------------
))
- $(TR $(TD $(XREF date, daysInMonth))
+ $(TR $(TD $(D daysInMonth))
$(TD $(SYSTIME).$(D endOfMonthDay); Actually, this name is overly
easy to confuse with $(D endOfMonth) - which returns a
$(SYSTIME) of the last day of the month. I will probably
rename this to $(D daysInMonth). But if I do, it won't be
until the next release (2.054), and this name will be around
until it's gone through the full deprecation cycle.))
- $(TR $(TD $(XREF date, UTCtoString))
+ $(TR $(TD $(D UTCtoString))
$(TD There is no equivalent. You could probably parse and recombine
$(D core.stdc.time.ctime) and
$(SYSTIME).$(D toISOExtString) to create it though. However,
this function appears to be fairly buggy in the first place,
so odds are that your code isn't using it anyway.))
- $(TR $(TD $(XREF date, toUTCString))
+ $(TR $(TD $(D toUTCString))
$(TD There is no equivalent. You could probably parse and recombine
$(D core.stdc.time.ctime) and
$(SYSTIME).$(D toISOExtString) to create it though.))
- $(TR $(TD $(XREF date, toDateString))
+ $(TR $(TD $(D toDateString))
$(TD There is no equivalent. You could probably parse and recombine
$(D core.stdc.time.ctime) and
$(SYSTIME).$(D toISOExtString) to create it though. However,
this function appears to be fairly buggy in the first place,
so odds are that your code isn't using it anyway.))
- $(TR $(TD $(XREF date, toTimeString))
+ $(TR $(TD $(D toTimeString))
$(TD There is no equivalent. You could probably parse and recombine
$(D core.stdc.time.ctime) and
$(SYSTIME).$(D toISOExtString) to create it though. However,
this function appears to be fairly buggy in the first place,
so odds are that your code isn't using it anyway.))
- $(TR $(TD $(XREF date, parse).$(D parse))
+ $(TR $(TD $(D parse).$(D parse))
$(TD $(SYSTIME).$(D fromISOString),
$(SYSTIME).$(D fromISOExtString), and
$(SYSTIME).$(D fromSimpleString), but the formats of the
- strings differ from what $(FULL_XREF date, parse) accepts.))
- $(TR $(TD $(XREF date, getUTCtime))
+ strings differ from what $(D std.date.parse) accepts.))
+ $(TR $(TD $(D getUTCtime))
$(TD $(D Clock.currTime(UTC())) if you want the $(SYSTIME) to have
its time zone be $(UTC). More likely though, you'll just use
$(D Clock.currTime()). Its internal time is in UTC
regardless.))
- $(TR $(TD $(XREF date, DosFileTime))
- $(TD $(XREF datetime, DosFileTime)))
- $(TR $(TD $(XREF date, toDtime))
- $(TD $(XREF datetime, DosFileTimeToSysTime)))
- $(TR $(TD $(XREF date, toDosFileTime))
- $(TD $(XREF datetime, SysTimeToDosFileTime)))
- $(TR $(TD $(XREF date, benchmark))
- $(TD $(XREF datetime, benchmark)))
+ $(TR $(TD $(D DosFileTime))
+ $(TD $(REF_SHORT DosFileTime, std,datetime)))
+ $(TR $(TD $(D toDtime))
+ $(TD $(REF_SHORT DosFileTimeToSysTime, std,datetime)))
+ $(TR $(TD $(D toDosFileTime))
+ $(TD $(REF_SHORT SysTimeToDosFileTime, std,datetime)))
+ $(TR $(TD $(D benchmark))
+ $(TD $(REF_SHORT benchmark, std,datetime)))
)
$(P Note that I'm not an expert on what does and doesn't work in
@@ -751,49 +753,41 @@ int dateFromNthWeekdayOfMonth(int year, Month month,
$(STD_DATETIME) and will get you well on your way to being able to
migrate your code from $(STD_DATE) to $(STD_DATETIME). If you have any
further questions, please ask them on the
- $(WEB www.digitalmars.com/NewsGroup.html, digitalmars.D.learn newsgroup).
+ $(HTTP www.digitalmars.com/NewsGroup.html, digitalmars.D.learn newsgroup).
And if there's a major use case of $(STD_DATE) which is not easy to
convert over to $(STD_DATETIME) which I missed in this
article and you think should be in it, please feel free to bring it up
on the
- $(WEB www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup),
+ $(HTTP www.digitalmars.com/NewsGroup.html, digitalmars.D newsgroup),
and if need be, I'll update this article with the relevant information.)
)
Macros:
- CATEGORY_ARTICLES=$0
- BOOKTABLE =
+
+ $(P
+ The universal reason I've heard from the turncoats was $(DOUBLEQUOTE productivity.) The consensus seems to be that programmers are more productive using Java, C#, Ruby, or Python than they are using C++.
+ )
+
+ $(P
+ What are the major impediments to productive programming in C++?
+ )
+
+ $(P
+ $(B Horrible syntax) is one. This is actually more serious than it sounds. A good programmer can probably master some pretty horrible syntaxes given enough time. The problem is that C++ syntax and grammar is not only human-unfriendly but also parser-hostile. The fact that the Java market is saturated with productivity boosting tools is the reflection of the language's parseability. I have to yet see a C++ programming environment that would offer such powerful refactoring tools as are commonplace in Java.
+ )
+
+ $(P
+ Language safety is the other major factor. C++ is notorious for presenting a never ending gallery of opportunities to shoot yourself in the foot. In fact C++ not only provides the opportunity to write dangerous code, it $(I encourages ) it. At some point a major C++ compiler vendor marked a portion of STL algorithms as "deprecated" because of safety concerns. In particular the C++ Standard Library, in accordance with the spirit of C++, extends the number of ways a buffer overflow bug might sneak into your program.
+ )
+
+ $(P
+ One notorious example is the $(CODE std::swap_ranges) algorithm, which takes three iterators. The first two iterators are supposed to delimit one range, the third one marks the beginning of the second range. No testing is done whether the second range doesn't extend past the end of the container. When it does, virus writers rejoice!
+ )
+
+ $(P
+ The pipe dream of programming language designers is to be able to guarantee that if a program compiles successfully, it will work. Of course you have to be reasonable about your definition of a "working" program. For instance, you might require that the program will never get "stuck"—a term which has a precise meaning in computer science, but loosely means that the program will not GP-fault on you (it is stuck in the sense that there is no well-defined system-independent next step). Languages that have such a property are called "sound".
+ )
+
+ $(P
+ Guess what, there is a well-defined (and meaningful) subset of Java that is sound. Real-life Java programs, for practical reasons, stray outside of this sound subset; but at least the use of unsafe features is less prevalent and easier to spot in a Java program than it is in a C++ program. In practice, a Java compiler will detect more bugs in your program than a C++ compiler, and that translates directly into less time spent debugging—ergo, higher productivity.
+ )
+
+ $(P
+ So what are the good features of C++?
+ )
+
+ $(P
+ Performance is one. It's really hard to beat C++ performance. If your program has to be fast and responsive you have little choice but to write it in C++ (or, in rare cases, in C or assembly).
+ )
+
+ $(P
+ Then there are the low-level features of C++ that let you write programs interacting directly with hardware. For instance, C and C++ are still kings of embedded programming.
+ )
+
+ $(P
+ C++ offers powerful abstractions, in particular the ability to write generic code. Java and C# have their own generics but they are feeble compared to what C++ has to offer.
+ )
+
+ $(P
+ All these features make C++ an ideal language for writing operating
+ systems. Operating systems are huge programs that have to be fast and
+ interact directly with hardware. But even outside operating systems
+ there are a lot of applications that have to be large and fast.
+ )
+
+ $(P
+ So it looks like the programming world could be nicely partitioned between C++, Java, C# and the likes. And it all makes sense as long as you believe in the unavoidability of tradeoffs. But there is no law of nature that says, $(I You have to trade productivity for power).
+ )
+
+ $(P
+ What about a language that is built like an onion. It has a reasonably simple and safe core, which is not unlike Java or C#. A programmer can quickly master a safe subset of it and be as productive as a Java programmer (if not more). And what if the safe subset offered performance that was comparable to C++?
+ )
+
+ $(P
+ And then, the same language has outer layers that can be mastered gradually, as the need arises. It offers low-level features to grind the hardware, and high-level features to generate code on demand. It offers modularity and implementation hiding. It has unrivaled compile time features that enable lightning fast runtime performance.
+ )
+
+ $(P
+ I'll let you in on a secret, this language is D.
+ )
+
+ $(SECTION2 $(LNAME2 pitfalls, Programming Pitfalls),
+
+
+ $(P
+ Did you know that the famous $(CODE"Hello World!") program, which is usually the first program people write in C, exposes some of the most dangerous features of the language? It contains this statement:
+ )
+
+ $(CCODE
+printf ("Hello World!\n");)
+
+ Consider the signature of $(CODE printf):
+
+ $(CCODE
+int printf (const char * restrict format, ...); )
+
+ $(P
+ ($(CODE restrict) is a new C keyword.) First of all, it's a function that takes a variable number of arguments. The number and the types of arguments are encoded in the format string.
+ )
+
+ $(P
+ When is the match between the format and the argument list checked? Not at compile time—the compiler has no understanding of the format string (although some compilers may issue warnings if the string is statically known). At runtime then? Well, guess again. Consider this: If the programmer makes a mistake of calling printf with too few arguments, he or she will not get a nice error code or exception. Here's what the C Standard says about this situation:
+ )
+
+
+
+BREADCRUMBS=$(BREADCRUMBS_FULL)
+
+BREADCRUMBS_DIV=
+)
+$(BR)
+
+
)