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








"Meta" <jared771 gmail.com>