One more shot at this const thing.

Dave Dave_member at pathlink.com
Thu Jul 27 09:09:09 PDT 2006


I can still hear the horse whinnying, so I thought I'd beat it with a 
slightly different club <g> And that would be taking the best of C++ 
const modified to be more in line with D goals. I don't think the exact 
same has been outlined before, so if it has I apologize.

IIRC Walter's primary (and valid IMO) arguments against C++ const are:

1) it does not guarantee anything to a code maintainer
2) it does not guarantee anything to the compiler
3) it's ugly (const sprinkled everywhere).

But, I'm beginning to think that maybe C++'s const [with roughly the 
same compiler enforcement rules but slightly different semantics and 
syntax more applicable to D] would work Ok.

Also maybe const would apply only to built-in reference types (including 
class objects) and not pointers, justifiable because D has these 
built-in whereas C++ doesn't. The same 'const' would not apply to value 
types either, for simplicity.

Consider the following C++ code:

class C
{
public:
     const char *str;
     C(const char *val): str(val)
     {
     }
     char
     const *           // const reference data return value
     foo(char          // const reference data
         const *       // const reference data
         const val     // const reference
        ) const        // const object
     {
         val = new char[100]; // error: assignment of read-only parameter
         val[0] = 'a';        // error: assignment of read-only location
         str = new char[100]; // error: assign to member of const object
         str[0] = 'a';        // error: assignment of read-only location
         return str;
     }
     int i;
     void bar(int val) { i = val; }
     int baz() const
     {
         return i;
     }
};

int main()
{
     C c("test string");
     char* str, *st2;
     st2 = c.foo(str); // error: invalid conversion const char* to char*
     const char* st3 = c.foo(str); // Ok
     return 0;
}

int bar(const C &c)
{
     c.i = 10; // error: assignment of data-member in read-only structure
     c.foo("test");
     c.bar(10); // error: discards qualifiers
     return c.baz() * 10;
}

So in D this would be:

class C
{
     const char[] str;
     this(char[] val)
     {
         str = val;
     }
     // const reference & data for return value, argument and object
     // ugly, but necessary and not nearly as ugly as C++
     const char[] foo(const char[] val) const
     {
         val = new char[100]; // error: assignment of read-only parameter
         val[0] = 'a';        // error: assignment of read-only location
         str = new char[100]; // error: assign to member of const object
         str[0] = 'a';        // error: assignment of read-only location
         return str;
     }
     int i;
     void bar(int val) { i = val; }
     int baz() const
     {
         return i;
     }
}

void main()
{
     C c = new C("test string");
     char[] str, st2;
     st2 = c.foo(str); // error: conversion from const char[] to char[]
     const char[] st3 = c.foo(str); // Ok

     // The C++ rules plus all this looks readily enforceable by the
     //  compiler to me.
     st2 = cast(char[])c.foo(str); // error: invalid cast
     st2 = st3; // error
     str[0] = st3[0]; // Ok
     st3 = st2; // error
     st3 = cast(const char[]) st2; // error: invalid cast
     st3[0] = st2[0]; // error
     const char* ptr; // error, invalid type (how much broken code?)
}

int bar(const C c)
{
     c.i = 10; // error
     c.foo("test"); // Ok
     c.bar(10); // error
     return c.baz * 10; // Ok
}

The compiler can't enforce everything you can do to a const in D. To 
make it so that const can actually be meaningful, additional language 
could be added to the spec. That language could be as simple as 
something like: "subverting const can result in undefined behavior".

This spec. language is justifiable (again) because D has built-in 
reference types that C++ doesn't, and it's done like that for numerous 
other things in D (e.g.: missing return statements and order of 
evaluation) so it's not inconsistent.

I think all of the above is enforceable for a compiler (so it's 
meaningful in the general case) and also is not as ugly or convoluted as 
C++ syntax. I believe it takes care of the issues of a) not having any 
help by the compiler on enforcing COW and b) being able to pass class 
and other reference objects into a function and 'guarantee' that the 
object not be modified inside the function.

The actual keyword used is not important.

One of the major reasons Java is slow is because of all the data 
duplication that needs to go on. D needs to avoid this... Billions of $ 
and years of research into Java GC and runtime optimizers has not solved 
the problem, leading me to believe it never will. If D gets the same rap 
as Java on the perf. issues, game over. Likewise if programmer-only 
enforced COW turns out to be a bug-ridden maintenance nightmare for 
corporate programmers out there.

Thoughts on this method of 'const' for D?

Thanks,

- Dave



More information about the Digitalmars-d mailing list