Bypassing const with a union
Era Scarecrow
rtcvb32 at yahoo.com
Fri Jun 1 13:24:37 PDT 2012
While working on the BitArray I've come across an interesting
dilemma, which is both bad and good. Let's take the following
struct S {
size_t[] array;
}
Simple enough, however make a const function, and suddenly you
can't return a copy of it.
S copy() const {
return this; //compile-time error
}
Not bad, type system is doing it's job. Let's say I want to
adjust the pointer as a slice
S opSlice(int s, int e) { //non-const-able call
S sl;
sl.array = this.array[s .. e];
return sl;
}
Good, but if I wanted to return an const item (as above) we have
an issue. Since I want to change the pointer (but not it's
contents) as a slice, the const system gets in the way without
duping it.
//from const, to const
const(S) opSlice(int s, int e) const {
S s = this; //compile error this.array is const
s.array = this[s .. e]; //compile error
return s;
}
The item starts as const and ends as const and no data (other
than maybe the struct which is new) changes; we should be able to
adjust the pointer if we want. If I use a union I can bypass this.
struct S {
union {
size_t[] array;
size_t[array.sizeof / size_t.sizeof] nonConst; //since it's a
fixed array
}
const(S) opSlice(int s, int e) const {
S sl;
sl.nonConst = nonConst; //bypass const!
sl.array = sl.array[s .. e];
return sl;
}
}
Part of the simpler solutions go away when I try to const a
struct when cast's have already been declared as with BitArray's
original design. Meaning I couldn't just do this:
return const(BitArray) s; //template not found for opCast(T) or
something
Would I use const within the cast?
const(BitArray) opCast(T : BitArray)() { //or something similar?
return const(BitArray) b; //infinite loop?
}
Although this means it could be quite dangerous, used in the
right way it can also be a good thing. However consider this:
union X {
string str;
char[] chr;
}
char[] nonConstString(string inString){
X x;
x.str = inString;
return x.chr; //immutable becomes non-immutable?
}
void bomb() {
auto ncs = nonConstString("Go Boom!");
ncs[0] = '!'; //should blow up or seg fault?
writeln(ncs); //in my own test it silently succeeds
}
Thinking about it, although this is possible you might still
allow it but send warnings when the compiler detects it. Reason?
Const takes effect too soon, sometimes before you can finish
working on the changes. I've tried moving them to a new
constructor(s) but keep having issues when the inputs are const
as the struct assumes it's starting non-const. I think...
Breaking the const system while your still building/preparing
the new object should be allowed (as with the slice example) but
once you pass it out it shouldn't be allowed anymore.
More information about the Digitalmars-d-learn
mailing list