Perfect D
Difference (last change) (no other diffs, normal page display)
Deleted: 552,662d551
Imperfect C++ and more perfect D
Introduction
Matthew Wilson gives a list of imperfections and constraints of C++ in his book "Imperfect C++ Practical Solutions for Real-Life Programming". I found out Digitalmars D language gives the positive answer of those questions. This paper tries to make them practical.
Note that these comments were probably based on a pre-1.0 version of DMD.
Organization
Each item consists of three part, the Wilson's rule, the practice of D, the explanation
Item 1
Imperfection: C++ does not provide direct support for constraints. (p. 4)
Answer:
template Constraint(T, U) { const bool sameType = is(T == U); const bool convertable = is(T : U);Explanation: The most correct answer is compile time reflection, in my opinion. D's built-in compile time constraint almost approaches the goal.const bool structType = is(T == struct) && is(T == struct); const bool classType = is(T == class) && is(T == class);
const bool derived = convertable && !sameType && classType; }
class a { }
class b : a { }
mixin Constraint!(b, a) b_a; mixin Constraint!(a, b) a_b;
static assert(Constraint!(b, a).derived);
Item 2
Imperfection: C++ does not provide suitable support for postconditions. (p. 15)
Answer:
void func() in { assert(input and precondition) } out { assert(output and postcondition) } body { the function body; }Explanation: DBC is builtin in D.
Wilson suggests:
Recommendation: Use assertions to assert truths about the structure of the code, not about runtime behavior. (p. 21)
In D, using DBC for precondition and postcondition. using assert for runtime behavior and static assert for structure of the code.
Item 3
Imperfection: The C++ standard does not define an ABI, leading to wholesale incompatibilities between many compilers on many platforms. (p. 92)
Answer:
D has a partial description of an ABI in the specification (but it's still in progress). See D 1.x /
D 2.x
Explain: Walter (the author of D) does a lot work to avoid the incompatibilities between compiler providers. He released the D front end under an open source license. I think each D compiler writer should use it as a reference implementation.
Item 4
Imperfection: C++ is not a suitable module-interface language. (p. 121)
Answer: D has modules.
Item 5
Imperfection: C and C++ say nothing about threading. (p. 132)
Answer: As Java, D has a synchronized keyword.
Item 6
Imperfection: C++ does not provide a mechanism for controlling global object ordering. (p. 158)
Answer:
There are two parts to global object initialization, in module and inter module. in module: module scope static this(){} is a module constructor which initializes all static objects in the module. inter module: module is instanced by importation order.Explain:
in module, the static this() constructor is fairly good for initializing. The order of object constructing can be managed well, but the importation order is not as controllable as in module global object.
Recommendation: Don't rely on global object initialization ordering. Do utilize global object initialization ordering tracing mechanisms anyway. (p. 161)
Recommendation: Don't create threads during global object initialization. (p. 166)
Item 7
Imperfection: Function-local static instances of classes with nontrivial constructors are not thread-safe. (p. 171)
Answer:
Wouldn't this work: func(...) { static className instance=null; synchronized { if( instance == null ) { instance = new className(...); } } } -- MerlinMM?Explain:
instance exists as null reference at program start time (global static program data). The constructor call only happens at 'new className(...)' which is thread safe due to the global mutex setup by the synchronized keyword.Should we ask for an extension to the language to allow say: func(...) { synchonized static className instance; } to effectively given us this functionality. Please let me know if I'm missing something. -- MerlinMM?
Item 8
Imperfection: The support for Empty Base Optimization (EBO) flavors is not universal, and varies significantly between compilers. (p. 183)
Item 9
Imperfection: C and C++ are missing a byte type. (p. 191)
Answer:
D has both byte and ubyte (unsigned byte) type.
Item 10
Imperfection: C and C++ need fixed-sized integer types. (p. 195)
Answer:
All type sizes are fixed and initial values are defined.
|
Item 11
Imperfection: C++ needs fixed sized types that are different to, and not implicitly interconvertible with, its built-in integral types. (p. 196)
Answer:
import std.stdint; //for typedef int8_t ...class Serializer { // Operations public: void Write(int8_t i){} void Write(uint8_t i){} void Write(int16_t i){} void Write(uint16_t i){} void Write(int32_t i){} void Write(uint32_t i){} void Write(int64_t i){} void Write(uint64_t i){}
}
void fn() { auto Serializer s = new Serializer; int8_t i8 = 0; int64_t ui64 = 0; int i = 0;
s.Write(i8); s.Write(ui64); s.Write(i); //Ambiguous call in C++, valid in D s.Write(0); //Ambiguous call in C++, valid in D }
int main() { fn();
return 0; }
Item 12
- Imperfection:* C and C++ do not provide large fixed-sized integer types. (p. 200)
- Answer:*
Item 13
Imperfection: bool should be the same size as int. (p. 205)
Answer: D has a 1 byte bool type.
Explain:
Initially D used a bit to represent bool but as per the discussion Boolean != Bit, D has bool.
Item 14
Imperfection: C and C++ do not provide a dimensionof() operator (for array types). (p. 207)
Answer: array.length is the dimensionof() operator.
int[] a = ...; a.length; // return dimension of a;
Item 15
Imperfection: Inability to distinguish between arrays and pointers can result in static array size determination being applied to pointers or class types, yielding incorrect results. (p. 211)
Answer:
Array and pointer are different types.
int* p; int[] a;Explain:p = a; // ok a = p; // fail a = p[0 .. 3]; //specify dimension.
static if(is(typeof(a) U == U[])) { static assert( is(U == int)); }
static if(is(typeof(a) U == U*)) //fail { static assert(0); }
static if(is(typeof(p) U == U*)) { static assert( is(U == int)); }
static if(is(typeof(p) U == U[]))//fail { static assert(0); }
Item 16
Imperfection: C and C++ arrays decay into pointers when passed to functions. (p. 214)
Answer:
void func(int[] b); void func(int* b);These are overloaded functions;
Item 17
Imperfection: C++'s array/pointer duality, combined with its support for polymorphic handling of inherited types, is a hazard against which the compiler provides no assistance. (p. 218)
Answer:
D is good here!
Item 18
Imperfection: C++ does not support multi-dimensional arrays. (p. 224)
double[3][3] matrix; //Rectangular? Array; (big array with two dimensional access) double[][] matrix; //two dimensional Array;(array of array)
Item 19
Imperfection: C++ needs a null keyword, which can be assigned to, and equality compared with, any pointer type, and with no non-pointer types. (p. 229)
Answer: Yes, null is a keyword in D, and it can initialize no primary type.
Explain:
Item 20
Imperfection: Having more than one discrete value for the Boolean type is dangerous. (p. 236)
Answer:
D has a bool type for true and false; int which used as boolean type in D, evaluated zero as false, and no-zero for true;
Item 21
Imperfection: Specification of the size of integer types as implementation dependent in C/C++ reduces the portability of integer literals. (p. 238)Answer:
integer literals evaluated as its smallest fixed-size integer;
Item 22
Imperfection: C++ compilers do not agree on the syntax for suffixes of integer literals larger than those that will fit into (unsigned) long. (p. 239)Answer:
this is error at debug mode;
Item 23
Constraint: C and C++ do not guarantee to ensure that identical string literals will be folded within a single link unit, and cannot do so across separate link units. (p. 242)
Answer:
I know nothing about this in D.
Item 24
Constraint: Casting away constness of a constant object is not legal, and will likely lead to unintended consequences. (p. 245)
Answer:
D allows both const and immutable to be cast away, this is because casting circumvents the type system, D just hopes you know what you are doing.
Item 25
Constraint: Constants of class type are evaluated as immutable global objects, rather than as compile-time constants. Failure to be mindful of this distinction is hazardous. (p. 246)
Answer:
constants is the compile time constants.Recommendation: Avoid using enum values larger than those that will fit in an int. (p. 248)
Item 26
Imperfection: C++ does not support member constants of floating-point type. (p. 249)
Answer:
no such constants;
Item 27
Constraint: C++ does not support member constants of class type. (p. 250)
Answer:
no such constants;Recommendation: Never attempt to simulate class-type member constants with function local static objects. (p. 251)
Item 28
Imperfection: C++ does not provide access control between types involved in a composition relationship. (p. 257)
Answer:
package is the access modifer, for module scope public;
Item 29
Imperfection: The introduction of new keywords into the language requires contingency mechanisms
to maintain portability. (p. 268)Answer:
Maybe later, but not now;
Item 30
Imperfection: Abuse of C++'s last-known access specifier mechanism leads to code that is hard to use and hard to maintain. (p. 271)
Answer:
public: void member();public void member();
public{ void member(); ... }
all above is legal, which would you like? go ahead.
Item 31
Imperfection: Implicitly interpreting non-Boolean (sub-)expressions leads to failure to be mindful of the values of certain types, with a consequent propensity to over-engineer user-defined types. (p. 274)
Answer
Item 32
Imperfection: The implicit interpretation of scalar types as Boolean in conditional statements facilitates erroneous assignment caused by syntax errors. (p. 275)
Item 33
Imperfection: The contradiction between the old and new for-statement rules results in non-portable code. (p. 278)
Item 34
Imperfection: for statements requiring initializers of two or more types render the new for-scoping rule irrelevant. (p. 279)
Item 35
Imperfection: C++ provides no type-safety for the use of conceptual defined types, except where such types have incompatible underlying types. (p. 294)
Item 36
Imperfection: C++ does not support overloading on conceptually defined types, except where such types happen to have different underlying types on a particular platform. (p. 294)
Answer
Recommendation: Avoid making conceptual typedefs that are comprised of contextual typedefs. (p. 304)
Item 37
Imperfection: Logically related types in C++ can, and usually do, have incompatible interfaces and operations, rendering a generalized approach to type manipulation sometimes difficult, and often impossible. (p. 341)
Answer
opCmp is only relationship operator overloading. opEqual is only identification operator overloading.
Item 38
Imperfection: The C++ template mechanism instantiates a template based on the arguments to it, and takes no account of how, or in what form, those arguments are subsequently used within the templates. This can lead to the generation of inefficient and/or erroneous code since temporary instances of class type may be created during the forwarding of arguments through the template. (p. 387)
Answer
Maybe true or no true.
Item 39
Imperfection: Overloading operator &() breaks encapsulation. (p. 425)
Answer
operator & can overload.
Item 40
Imperfection: Provision of implicit conversion operator(s) to pointer type(s) along with subscript operator(s) is non-portable. (p. 434)
Item 41
Imperfection: Some C++ compilers will substitute prefix increment/decrement overloaded operators at the call site in place of absent postfix equivalents. (p.440)
Answer
never
Item 42
Imperfection: Overloading the && and || operators for class types represents an invisible breaking of short-circuit evaluation. (p. 454)
Answer && and || can not overload.
Item 43
Imperfection: C and C++ make you choose between performance and flexibility when allocating memory. (p. 476)
Answer
D has choosen a little of both for you. You can allocate items on stack with scope keyword. You can define your own class allocators if you like malloc/free, but by default you get garbage collector which adds flexibility (e.g. dynamic arrays).
Item 44
Imperfection: C/C++ does not support dynamically dimensioned multidimensional arrays. (p. 491)
Answer
Recommendation: An array size shim should always be used when determining the sizes of arrays, as all other approaches do not generalize for both built-in and user defined array types. (p. 505)
Item 45
Imperfection: C++ does not support local functor classes (to be used with template algorithms). (p. 514)
Answer:
local class is there.
Item 46
Imperfection: C++ does not provide properties. (p. 531)
Answer
built-in properties:int.sizeof yields 4 float.nan yields the floating point nan (Not A Number) value (float).nan yields the floating point nan value (3).sizeof yields 4 (because 3 is an int) 2.sizeof syntax error, since "2." is a floating point number int.init default initializer for int'
user properties is easy:
struct Foo { int data() { return m_data; }// read property
int data(int value) { return m_data = value; } // write property
private: int m_data; }
int test() { Foo f;
f.data = 3;// same as f.data(3); return f.data + 3;// same as return f.data() + 3; }