Thread overview
opIndex overload for slice not working...
Jan 25, 2016
Enjoys Math
Jan 25, 2016
biozic
Jan 25, 2016
Ali Çehreli
January 25, 2016
class V(T) {
public:
   this() {}
   V opIndex(size_t i, size_t j) {
     writeln("Hello, foo!");
     return this;
   }
}

main() {
   auto v = new V!int();
   auto u = v[3..4];        // ERROR
}

Error:
no [] operator overload for type the_module.V!int
January 25, 2016
On Monday, 25 January 2016 at 06:37:13 UTC, Enjoys Math wrote:
> class V(T) {
> public:
>    this() {}
>    V opIndex(size_t i, size_t j) {
>      writeln("Hello, foo!");
>      return this;
>    }
> }
>
> main() {
>    auto v = new V!int();
>    auto u = v[3..4];        // ERROR
> }
>
> Error:
> no [] operator overload for type the_module.V!int

You're mixing slicing and indexing. Use *opSlice* to support i..j slicing notation.

---
import std.stdio;

class V(T) {
public:
   this() {}

   V opIndex(size_t i, size_t j) {
     writeln("Indexing");
     return this;
   }

   V opSlice(size_t i, size_t j) {
     writeln("Slicing");
     return this;
   }
}

void main() {
   auto v = new V!int();
   auto w = v[3, 4]; // Indexing
   auto u = v[3..4]; // Slicing
}
---

January 24, 2016
On 01/24/2016 10:37 PM, Enjoys Math wrote:
> class V(T) {
> public:
>     this() {}
>     V opIndex(size_t i, size_t j) {
>       writeln("Hello, foo!");
>       return this;
>     }
> }
>
> main() {
>     auto v = new V!int();
>     auto u = v[3..4];        // ERROR
> }
>
> Error:
> no [] operator overload for type the_module.V!int

That usage used to be supported by opSlice. Here is my interpretation of it:


http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.opSlice

However, with relatively recent changes to D, expressions like v[3..4] are now represented more powerfully by opIndex() templates. Expressions 3..4 must first be passed through an opSlice() template to describe what it means to your type.

Usually, 3..4 can trivially be represented by a Tuple!(size_t, size_t) (or by a custom type):

   struct Range {
       size_t begin;
       size_t end;
   }

   Range opSlice(size_t dimension)(size_t begin, size_t end) {
       return Range(begin, end);
   }

My interpretation of this new scheme is at


http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.multi-dimensional%20operator%20overloading

Here is your code with those changes:

import std.stdio;

class V(T) {
public:
   this() {}

   struct Range {
       size_t begin;
       size_t end;
   }

   // Could return a Tuple
   Range opSlice(size_t dimension)(size_t begin, size_t end) {
       return Range(begin, end);
   }

   V opIndex(A...)(A args) {
       foreach (dimension, arg; args) {
           writefln("dimension: %s, accessing %s", dimension, arg);
       }
       return this;
   }
}

void main() {
   auto v = new V!int();
   auto u = v[3..4];
}

Prints

dimension: 0, accessing Range(3, 4)

Ali