www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Should opIndex completely override alias this?

reply Trass3r <un known.com> writes:
As soon as you define an opIndex, alias this isn't considered anymore.
Is this wanted behavior?

I'd have expected this to work:

	T[] data;
	T opIndex(size_t i, size_t j)
	{
		return data[i*numCols+j];
	}
	alias data this;

Then dynmap[3] would work by using data directly.
But: opIndex (ulong i, ulong j) is not callable using argument types (int)
May 11 2012
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2012/5/12 Trass3r <un known.com>:
 As soon as you define an opIndex, alias this isn't considered anymore.
 Is this wanted behavior?

 I'd have expected this to work:

 =A0 =A0 =A0 =A0T[] data;
 =A0 =A0 =A0 =A0T opIndex(size_t i, size_t j)
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return data[i*numCols+j];
 =A0 =A0 =A0 =A0}
 =A0 =A0 =A0 =A0alias data this;

 Then dynmap[3] would work by using data directly.
 But: opIndex (ulong i, ulong j) is not callable using argument types (int=
) This is expected behavior. 'alias this' works as proper super type. struct S { T[] data; alias data this; } In this code, S behaves as it is derived from T[] . Following to this view, the definition of opIndex in S overrides (and hides) T[]'s opIndex completely. Kenji Hara
May 11 2012
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S 
 overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
May 11 2012
next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2012/5/12 Mehrdad <wfunction hotmail.com>:
 On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
I'll add 'forwarding opIndex'. struct S(T) { T data; alias data this; int opIndex()(size_t i, size_t j) { return 100; // specialized opIndex } auto opIndex(A...)(A args) if (A.length != 2) { return data[args]; // forwarding } } void main() { auto s = S!(int[])([1,2]); assert(s[1,2] == 100); assert(s[0] == 1); assert(s[1] == 2); }
May 11 2012
parent David <d dav1d.de> writes:
 struct S(T)
 {
      T data;
      alias data this;

      int opIndex()(size_t i, size_t j)
      {
          return 100; // specialized opIndex
      }
      auto opIndex(A...)(A args) if (A.length != 2)
      {
          return data[args];  // forwarding
      }
 }
 void main()
 {
      auto s = S!(int[])([1,2]);
      assert(s[1,2] == 100);
      assert(s[0] == 1);
      assert(s[1] == 2);
 }
I want alias :/ struct S(T) { T data; alias data this; int opIndex()(size_t i, size_t j) { return 100; // specialized opIndex } alias data.opIndex opIndex; }
May 11 2012
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 05/11/12 19:22, Mehrdad wrote:
 On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
Not quite sure what you mean, but auto opIndex(A...)(A a) { return data[a]; } artur
May 11 2012
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 11 May 2012 at 17:37:11 UTC, Artur Skawina wrote:
 On 05/11/12 19:22, Mehrdad wrote:
 On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S 
 overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
Not quite sure what you mean, but auto opIndex(A...)(A a) { return data[a]; } artur
What if it's const/pure/ safe/whatever though? Or the parameters have some attributes? (I guess this is a more general problem than opIndex specifically, though.)
May 11 2012
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 11 May 2012 13:47:13 -0400, Mehrdad <wfunction hotmail.com> wrote:

 On Friday, 11 May 2012 at 17:37:11 UTC, Artur Skawina wrote:
 On 05/11/12 19:22, Mehrdad wrote:
 On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
Not quite sure what you mean, but auto opIndex(A...)(A a) { return data[a]; } artur
What if it's const/pure/ safe/whatever though? Or the parameters have some attributes? (I guess this is a more general problem than opIndex specifically, though.)
D solves this by automatically adding pure safe nothrow to a template function, wherever it is possible. However, it doesn't do this for const or immutable. -Steve
May 11 2012
parent "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 11 May 2012 at 18:09:13 UTC, Steven Schveighoffer 
wrote:
 On Fri, 11 May 2012 13:47:13 -0400, Mehrdad 
 <wfunction hotmail.com> wrote:

 On Friday, 11 May 2012 at 17:37:11 UTC, Artur Skawina wrote:
 On 05/11/12 19:22, Mehrdad wrote:
 On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S 
 overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
Not quite sure what you mean, but auto opIndex(A...)(A a) { return data[a]; } artur
What if it's const/pure/ safe/whatever though? Or the parameters have some attributes? (I guess this is a more general problem than opIndex specifically, though.)
D solves this by automatically adding pure safe nothrow to a template function, wherever it is possible. However, it doesn't do this for const or immutable. -Steve
Yeah I remember that was a relatively recent fix, but there's still the issue of perfect forwarding that isn't possible in D: http://stackoverflow.com/questions/7948865
May 11 2012
prev sibling parent reply Artur Skawina <art.08.09 gmail.com> writes:
On 05/11/12 19:47, Mehrdad wrote:
 On Friday, 11 May 2012 at 17:37:11 UTC, Artur Skawina wrote:
 On 05/11/12 19:22, Mehrdad wrote:
 On Friday, 11 May 2012 at 17:19:28 UTC, kenji hara wrote:
 This is expected behavior.

 'alias this' works as proper super type.

 struct S { T[] data; alias data this; }

 In this code, S behaves as it is derived from T[] .

 Following to this view, the definition of opIndex in S overrides (and
 hides) T[]'s opIndex completely.

 Kenji Hara
How do you overcome this, in the case where you don't know the data type of 'data' (so you don't know what the overloads might look like, maybe because it's a template)?
Not quite sure what you mean, but auto opIndex(A...)(A a) { return data[a]; }
What if it's const/pure/ safe/whatever though? Or the parameters have some attributes?
Since it is a function template the attributes are inferred, in this case from data's opIndex, if any. The arguments are forwarded as-is, ie data's opIndex has to deal with them. The return type could be 'auto ref' too, then returning by reference would also magically work, but this is not always desirable, as it could leak private references; making return-by-ref explicit is probably safer in cases like this one. artur
May 11 2012
parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Friday, 11 May 2012 at 18:32:12 UTC, Artur Skawina wrote:
 Since it is a function template the attributes are inferred, in 
 this case from data's opIndex, if any. The arguments are 
 forwarded as-is, ie data's opIndex has to deal with them.
Among other things, 'scope' gets messed up.
May 11 2012
parent Artur Skawina <art.08.09 gmail.com> writes:
On 05/11/12 20:40, Mehrdad wrote:
 On Friday, 11 May 2012 at 18:32:12 UTC, Artur Skawina wrote:
 Since it is a function template the attributes are inferred, in this case from
data's opIndex, if any. The arguments are forwarded as-is, ie data's opIndex
has to deal with them.
Among other things, 'scope' gets messed up.
How? By making the forwarder not callable w/ a scoped argument, when the target function would be? It isn't a problem for operator overloading, as the signature(s) are known. But in general, scope-inference would be needed. Which has similar problems as 'uniq', for non-trivial function bodies. Yes, things aren't perfect; eg 'this' attributes/classes like shared or const also need explicit handling (recent frontend changes apparently improved the situation a bit). artur
May 11 2012
prev sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 05/11/12 19:03, Trass3r wrote:
 As soon as you define an opIndex, alias this isn't considered anymore.
 Is this wanted behavior?
 
 I'd have expected this to work:
 
     T[] data;
     T opIndex(size_t i, size_t j)
     {
         return data[i*numCols+j];
     }
     alias data this;
 
 Then dynmap[3] would work by using data directly.
 But: opIndex (ulong i, ulong j) is not callable using argument types (int)
That would mean a hidden opIndex overload (or more); not only can that make debugging harder, you then also would have to always make sure to override every opIndex present in 'data' if the indexing were to work differently in dynmap and T[]. Explicit forwarding is slightly more verbose, but much safer. artur
May 11 2012