digitalmars.D.learn - disable assignment of [] literal?
Consider the following code: struct ArrayWrapper(T) { T t; this(T t) { assert(t !is null); } disable this(typeof(null)); typeof(this) opAssign(T val) { assert(t !is null); this.t = val; return this; } disable typeof(this) opAssign(typeof(null)); disable typeof(this) opAssign(typeof([])); } void main() { //This is caught at compile time ArrayWrapper!(int[]) a = null; //This throwns a runtime error ArrayWrapper!(int[]) b = []; } That's fine, though, we can just add ` disable this(typeof([]))`. But wait, that doesn't work. The disable'd constructor is ignored and it takes the this(T t) constructor instead. I have no idea why, as this(typeof(void[])) should be more specialized than this(int[]) when called with `[]`, but okay. This isn't the only case that this doesn't work, either: ArrayWrapper!(int[]) b; //Caught at compile time, as expected b = null; //Throws a runtime error b = []; So in both cases, the compiler ignores the disable'd constructor and opAssign when called with `[]`. I tried changing them both to be templated, which made the "normal" constructor and opAssign less specialized than the disable'd ones. Fortunately, this strategy worked... sort of: struct ArrayWrapper(T) { T t; this(U)(U u) { assert(u !is null); } disable this(typeof(null)); disable this(typeof([])); typeof(this) opAssign(U)(u val) { assert(u !is null); this.t = val; return this; } disable typeof(this) opAssign(typeof(null)); disable typeof(this) opAssign(typeof([])); } void main() { //This is caught at compile time ArrayWrapper!(int[]) a = null; //This is caught at compile time too now. Awesome! ArrayWrapper!(int[]) b = []; ArrayWrapper!(int[]) a; //Caught at compile time a = null; ArrayWrapper!(int[]) b; //Now also caught at compile time b = []; } My hopes were instantly dashed when I tried the following: //Compile error. Okay... ArrayWrapper!(void[]) c = []; //This is also a compile error c = cast(void[])[1, 2, 3]; And the same for opAssign: ArrayWrapper!(void[]) c; //Compile error c = []; //Also a compile error c = cast(void[])[1, 2, 3]; So as you can see, it's more or less impossible to completely catch the assignment of [] to an array at compile time, even though it should be perfectly feasible. Is there any way I can accomplish this without making ArrayWrapper unusable for void[], or is a runtime check the best I can do?
Apr 25 2015
Use a different type to match empty slice instead of void[]? struct ArrayWrapper(T) { T t; this(T t) { assert(t !is null); } disable this(typeof(null)); disable this(ArrayWrapper[]); //should match [] typeof(this) opAssign(T val) { assert(t !is null); this.t = val; return this; } disable typeof(this) opAssign(typeof(null)); disable typeof(this) opAssign(ArrayWrapper[]); //should match [] }
Apr 27 2015
On Monday, 27 April 2015 at 14:30:26 UTC, Kagamin wrote:Use a different type to match empty slice instead of void[]? struct ArrayWrapper(T) { T t; this(T t) { assert(t !is null); } disable this(typeof(null)); disable this(ArrayWrapper[]); //should match [] typeof(this) opAssign(T val) { assert(t !is null); this.t = val; return this; } disable typeof(this) opAssign(typeof(null)); disable typeof(this) opAssign(ArrayWrapper[]); //should match [] }That won't work because I want to catch the [] literal, which is of type void[] and not ArrayWrapper[].
Apr 27 2015
Looks like it does: http://dpaste.dzfl.pl/a851acca63d9
Apr 28 2015
On Tuesday, 28 April 2015 at 07:43:28 UTC, Kagamin wrote:Looks like it does: http://dpaste.dzfl.pl/a851acca63d9That compiler error is because `ArrayWrapper!(int[]) = []` matches both `this(int[])` and `this(ArrayWrapper[])`, although... that might be workable.
Apr 28 2015