Hmm - about manifest/enum

Steven Schveighoffer schveiguy at yahoo.com
Wed Jan 2 05:58:32 PST 2008


"Walter Bright" wrote
> Steven Schveighoffer wrote:
>> How about doing an in-place sort of an array of const classes?
>
> Good question, and one that I wrestled with a lot. The answer is, just 
> like with strings, build another array.
>
>> const(C)[] myarray;
>>
>> ...
>> // swap two items i and j
>> auto tmp = myarray[i];
>> myarray[i] = myarray[j]; // error
>> myarray[j] = tmp; // error
>> ...
>>
>> Before you answer, building another array isn't acceptable, because that 
>> is a waste of resources and adds runtime.
>
> That's what our C intuition tells us, and that's why I resisted immutable 
> strings for so long. But the way caching works on modern processors, our 
> intuition about what is fast and slow about memory operations often is 
> wrong. Furthermore, the bug resistance of immutable strings I believe more 
> than makes up for it.

I think we are arguing different points here.  I am fine with const(T) 
meaning that T is const whether it be a class reference, or a struct, or 
primitive type.  I absolutely agree with that, and think it is required as 
you say.  My problem is that because classes are inherently references, you 
have to treat them that way, especially in regards to const.  If you can't 
split out the reference from the const-ness, then code is going to be extra 
awkward, and require workarounds that will at some point affect the 
complexity of algorithms.

I suppose my example is incorrectly stated, because with the current const 
system, you cannot state 'an array of mutable references to const classes'. 
So I agree that with an array of const class references:

const(C)[] myarray;

you should not be able to swap members.  But there should still be a way to 
specify an array of mutable references to const classes.  I don't care how 
it's done, but it cannot involve convoluted mechanisms to create backing 
arrays w/ pointers to references.  To have to allocate heap space to contain 
pointers when classes are already pointers seems inherently wasteful, and 
seems like I am fighting the language instead of having the language allow 
me to express what I want.

This is similar to not having constructors for structs.  If I want to create 
a const struct on the heap so I can store it somewhere outside the stack, 
instead of having a constructor I have to do:

S *s = new S;
s.value = 5;
const(S)*cs = s;

instead of:
const(S)*cs = new S(5);

Except in this case, the compiler can easily optimize the first to mean the 
second, and no bloat or runtime waste has occurred, because I'm just 
re-casting the pointer.  However for classes, I need:

C c = new C(5);
C *cp = new C*;
*cp = c;
const(C)* ccp = cp;

Now, I have an extra heap-allocated pointer for no good reason, and this is 
not optimized out by the compiler.

>> Tell me how you do this without having tail-const for class references. 
>> I couldn't care less about tail-const for structs, or tail-const for 
>> class instances (being defined as a state where the members of the 
>> class/struct are mutable, but any objects pointed to by its members are 
>> const).  This feature of being able to swap two references to const data 
>> is a very common algorithmic requirement.
>
> You're right, you cannot do it without tail-const for class references. 
> But if you're desperate, you can make it work using casting.

Sure, but the behavior is undefined, right? :P





More information about the Digitalmars-d mailing list