Jump to content

C++ Programming/Programming Languages/Comparisons/D

From Wikibooks, open books for an open world

The D programming language, was developed in-house by Digital Mars, a small US software company, also known for producing a C compiler (known over time as Datalight C compiler, Zorland C and Zortech C), the first C++ compiler for Windows (originally known as Zortech C++, renamed to Symantec C++, and now Digital Mars C++ (DMC++) and various utilities (such as an IDE for Windows that supports the MFC library).

Originally designed by Walter Bright it has, since 2006, had the collaboration of Andrei Alexandrescu and other contributors. While D originated as a re-engineering of C++ and is predominantly influenced by it, D is not a variant of C++. D has redesigned some C++ features and has been influenced by concepts used in other programming languages, such as Java, C# and Eiffel. As such, D is an evolving open-source system programming language, supporting multiple programming paradigms.

It supports the procedural, generic, functional and object-oriented paradigms. Most notably it provides very powerful, yet simple to use, compile-time meta-programming facilities.

It is designed to offer a pragmatic combination of efficiency, control, and modeling power, with safety and programmer productivity. Another of its goals is to be easy to use for beginners and to offer advanced capabilities when experienced programmers need them.

Supported platforms
[edit | edit source]

D is officially supported on Windows, Linux, OSX and FreeBSD on x86 and x86_64. Support in other platforms (Android, iOS and Solaris) and hardware (ARM, MIPS and Power-PC) is work-in-progress.

Compilers
[edit | edit source]

There 3 production ready compilers: DMD, GDC and LDC.

  • DMD is the reference implementation. The other two compilers share DMD's frontend. It offers very fast compilation, useful at development-time.
  • GDC uses GCC's backend for code-generation. It integrates well with the GNU toolchain.
  • LDC uses LLVM's backend. It can integrate well with other parts of the LLVM toolchain.
Interfacing with C and C++
[edit | edit source]

D can link directly with C and C++ (*) static and shared libraries without any wrappers or additional overhead (compared to C and C++). Supported subset of C++ platform specific ABI (e.g. GCC and MSVC):

  • C++ name mangling conventions, like namespaces, function names and other
  • C++ function calling conventions
  • C++ virtual function table layout for single inheritance

Generally D uses the platform linker on each platform (ld.bfd, ld.gold, etc. on Linux), the exception being Windows, where Optlink is used by default. MSVC link.exe is also supported, but the Windows SDK must be first downloaded.

D features missing from C and C++
[edit | edit source]

Some the new features that a C/C++ programmer will find are:

  • Design by introspection - one can design a templated class or struct to inspect its template arguments at compile-time for different capabilities and then adapts to them. For example, a composable allocator design can check if the parent allocator provides reallocation and efficiently delegate to it, or fallback to implementing reallocation with malloc() and free(), or not offer it at all. The benefit of doing this at compile-time is that the user of the said allocator can know if he should use reallocate(), instead of getting mysterious run-time errors.
  • True modules
  • Order of declaration and imports (#include-s in C++ terms) is insignificant. There is no need to pre-declare anything. You can rearrange things without change in meaning
  • Faster compilation - C++'s compilation model is inherently slow. Additionally compilers like DMD have further optimizations
  • More powerful conditional compilation without preprocessor
  • pure functions - side-effect free functions that are allowed to have internal mutation
  • Immutability - it is guaranteed that variables declared as immutable can be accessed safely from multiple threads (without locking and race-conditions)
  • Design by contract
  • Universal function call syntax (UFCS) - allow the free function void copyTo(T)(T[] src, T[] dst) to be called like this: sourceArray.copyTo(destinationArray)
  • Built-in unit testing
  • Garbage collection (optional)
  • scope control flow statement (partially emulated in C++ with the ScopeGuard idiom)

First class:

  • Dynamic arrays
int[] array; //declare empty array variable
array ~= 42; //append 42 to the array; array.equals([ 42 ]) == true
array.length = 5; //set the length to 5; will reallocate if needed
int[] other = new int[5]; // declare an array of five elements
other[] = 18; // fill the array with 18; other.equals([18, 18, 18, 18, 18]) == true
array[] = array[] * other[]; //array[i] becomes array[i] * other[i]
array[$ - 1] = -273; // set the last element to -273; when indexing an array the $ context variable is translated to array.length
int[] s = array[2 .. $]; // s points to the last 3 elements of array (no copying occurs).
  • Unicode strings
string s1 = "Hello "; // array of immutable UTF8 chars
immutable(char)[] s2 = "World "; // `s2` has the same type as `s1`
string s3 = s1 ~ s2; // set `s3` to point to the result of concatenating `s1` with `s2`
char[] s4 = s3.dup; // `s4` points to the mutable array "Hello World "
s4[$-1] = '!'; // change the last character in the string
s4 ~= "<-> Здравей, свят!"; // append Cyrillic characters that don't fit in a single UTF-8 code-unit

import std.conv : to;
wstring ws = s4.to!wstring; //convert s4 to an array of immutable UTF16 chars

foreach (dchar character; ws) // iterate over ws; 'character' is an automatically transcoded UTF32 code-point
{
    import std.stdio : writeln; // scoped selective imports	
    character.writeln(); //write each character on a new line
}

You can find a runnable example at dpaste.dzfl.pl - online compiler and collaboration tool dedicated to D.

  • Associative arrays
struct Point { uint x; uint y; } // toHash is automatically generated by the compiler, if not user provided
Point[string] table; // hashtable string -> Data
table["Zero"] = Point(0, 0);
table["BottomRight"] = Point(uint.max, uint.max);
  • Nested functions
  • Closures (C++11 added lambda functions, but lambda functions that capture variables by reference are not allowed to escape the function they were created in).
  • Inner classes
C++ features missing from D
[edit | edit source]
  • Preprocessor
  • Polymorphic types with non-virtual destructor
  • Polymorphic value-types - in D struct-s are value types without support for inheritance and virtual functions and class-es are reference types that support inheritance and virtual functions
  • Multiple inheritance - D classes offers only Java and C# style multiple implementation of interfaces. Instead, for code reuse D favors composition, mixins and alias this

See the D Programming book for more details.