const again

Christopher Wright dhasenan at gmail.com
Thu Dec 6 14:46:55 PST 2007


Walter Bright wrote:
>     TailConst!(C)[] a;
> which would do whatever was necessary under the hood to allow the 
> elements of a to be rebound while still keeping the contents of the C 
> objects const.

The TailConst template would probably need to be a struct:
struct TailConst (T) {
    static if (is (T == class) || is (T == interface)) {
       // can just store a reference
    } else {
       // assignment mallocs some memory and copies arg onto heap
       // store a ptr
    }
}

And then we'd need an opDot if we wanted transparent access. It's an 
annoyance, but a minor one, to have to use opDeref.


But I think perhaps the problem with arrays is that there's no way to 
say the array is not const, but its members are. The obvious syntax 
would be:
const(Foo)[] foos = new const(Foo)[5];
foos[2] = new Foo(); // ok

const(Foo[]) cfoos = new Foo[5];
cfoos[3] = new Foo(); // error; cfoos is const


Then string would be an alias to invariant(char[]) rather than 
invariant(char)[], which makes sense. It's not a mutable array of 
invariant characters.

However, this would suggest:
const(const(Foo)[]) ccfoos;

Which would suggest the cfoos array is a const buffer, but if it holds 
reference types, they are not const. And if the array is const, you 
can't rebind its elements.

The solution to that mess, if you need transitive const, is to define 
const(T[]) to be the same as const(const(T)[]), which won't affect 
primitives and value types but will get the desired result for reference 
types.

But it doesn't make sense to consider an array const if its elements are 
const; that would be extremely annoying with templates. If you wanted to 
use arrays for anything nontrivial, you'd have to start it with:
static if (is (T == const)) {
    alias TailConst!(T) ElemType;
} else {
    alias T ElemType;
}



More information about the Digitalmars-d mailing list