www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - disable assignment of [] literal?

reply "Meta" <jared771 gmail.com> writes:
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
parent reply "Kagamin" <spam here.lot> writes:
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
parent reply "Meta" <jared771 gmail.com> writes:
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
parent reply "Kagamin" <spam here.lot> writes:
Looks like it does: http://dpaste.dzfl.pl/a851acca63d9
Apr 28 2015
parent "Meta" <jared771 gmail.com> writes:
On Tuesday, 28 April 2015 at 07:43:28 UTC, Kagamin wrote:
 Looks like it does: http://dpaste.dzfl.pl/a851acca63d9
That compiler error is because `ArrayWrapper!(int[]) = []` matches both `this(int[])` and `this(ArrayWrapper[])`, although... that might be workable.
Apr 28 2015