www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templated opIndex?

reply OlaOst <olaa81 gmail.com> writes:
Here is a class with a templated opIndex method, and an attempt 
to use it:

class Test
{
	int[] numbers = [1, 2, 3];
	string[] texts = ["a", "b", "c"];
	
	Type opIndex(Type)(int index)
	{
		static if (is(Type == int))
			return numbers[index];
		static if (is(Type == string))
			return texts[index];
	}
}

void main()
{
	auto test = new Test();
	
	auto number = test[0]!int; // does not compile, syntax error
	auto number = test!int[0]; // does not compile, syntax error

	int number = test[0]; // does not compile, cannot deduce type
}


So it is possible to define a templated opIndex method in a 
class, but is it possible to use it? If not, should it be allowed 
to create templated opIndex methods?
Sep 19 2015
next sibling parent reply John Colvin <john.loughran.colvin gmail.com> writes:
On Saturday, 19 September 2015 at 09:33:02 UTC, OlaOst wrote:
 Here is a class with a templated opIndex method, and an attempt 
 to use it:

 class Test
 {
 	int[] numbers = [1, 2, 3];
 	string[] texts = ["a", "b", "c"];
 	
 	Type opIndex(Type)(int index)
 	{
 		static if (is(Type == int))
 			return numbers[index];
 		static if (is(Type == string))
 			return texts[index];
 	}
 }

 void main()
 {
 	auto test = new Test();
 	
 	auto number = test[0]!int; // does not compile, syntax error
 	auto number = test!int[0]; // does not compile, syntax error

 	int number = test[0]; // does not compile, cannot deduce type
 }


 So it is possible to define a templated opIndex method in a 
 class, but is it possible to use it? If not, should it be 
 allowed to create templated opIndex methods?
2 approaches: 1) use a function instead. E.g. test.get!int(0); isn't too bad 2) If you really want to use [], do something like this: class Test { int[] numbers = [1, 2, 3]; string[] texts = ["a", "b", "c"]; private struct Idx(T) { T data; auto opIndex(size_t index) { return data[index]; } } auto idx(Type)() property { static if (is(Type == int)) return Idx!(int[])(numbers); static if (is(Type == string)) return Idx!(string[])(texts); } } void main() { auto test = new Test(); auto number = test.idx!int[0]; auto text = test.idx!string[0]; }
Sep 19 2015
parent OlaOst <olaa81 gmail.com> writes:
On Saturday, 19 September 2015 at 10:16:58 UTC, John Colvin wrote:
 On Saturday, 19 September 2015 at 09:33:02 UTC, OlaOst wrote:
 [...]
2 approaches: 1) use a function instead. E.g. test.get!int(0); isn't too bad 2) If you really want to use [], do something like this: [...]
Thanks, option 1 is what I'm using today. It's a little annoying though, since templated OpIndexAssign works perfectly.
Sep 19 2015
prev sibling next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Saturday, 19 September 2015 at 09:33:02 UTC, OlaOst wrote:
 So it is possible to define a templated opIndex method in a 
 class, but is it possible to use it? If not, should it be 
 allowed to create templated opIndex methods?
test.opIndex!int(0) works?
Sep 19 2015
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
And this:

class TestInt: Test {
    alias opIndex = super.opIndex!int;
}

class TestString: Test {
    alias opIndex = super.opIndex!string;
}
Sep 19 2015
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
And this?

auto ref qua(T)(Test t){
   struct wrap {
     Test t;
     T opIndex(int i){ return t.opIndex!T(i); }
   }
   return wrap(t);
}


void main()
{
	auto test = new Test();
	writeln(test.qua!string[0], test.qua!int[0]);
}
Sep 19 2015
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 09/19/2015 02:33 AM, OlaOst wrote:
 Here is a class with a templated opIndex method, and an attempt to 
use it:
 class Test
 {
      int[] numbers = [1, 2, 3];
      string[] texts = ["a", "b", "c"];

      Type opIndex(Type)(int index)
      {
          static if (is(Type == int))
              return numbers[index];
          static if (is(Type == string))
              return texts[index];
      }
 }

 void main()
 {
      auto test = new Test();

      auto number = test[0]!int; // does not compile, syntax error
      auto number = test!int[0]; // does not compile, syntax error

      int number = test[0]; // does not compile, cannot deduce type
 }


 So it is possible to define a templated opIndex method in a class, but
 is it possible to use it? If not, should it be allowed to create
 templated opIndex methods?
Templated opIndex is used for multi-dimensional array indexing. The template arguments define the range of elements: http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.opIndex%20template And the spec: http://dlang.org/operatoroverloading.html#array-ops I would prefer the following: test.numbers[0]; test.texts[0]; but in addition to other solutions, here is another experiment: struct indexFor(T) { size_t idx; } class Test { int[] numbers = [1, 2, 3]; string[] texts = ["a", "b", "c"]; T opIndex(T)(indexFor!T index) { static if (is(T == int)) return numbers[index.idx]; static if (is(T == string)) return texts[index.idx]; assert(false); } } void main() { auto test = new Test(); auto number = test[indexFor!int(0)]; } Ali
Sep 19 2015