Thread overview
Templated opIndex?
Sep 19, 2015
OlaOst
Sep 19, 2015
John Colvin
Sep 19, 2015
OlaOst
Sep 20, 2015
Ali Çehreli
September 19, 2015
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?

September 19, 2015
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];
}

September 19, 2015
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.
September 19, 2015
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?

September 19, 2015
And this:

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

class TestString: Test {
   alias opIndex = super.opIndex!string;
}

September 19, 2015
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]);
}
September 20, 2015
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