digitalmars.D.learn - Chaining opIndex
- deed (43/43) May 09 2016 struct Foo {
- John Colvin (14/57) May 09 2016 There are lots of ways to approach this. Here's one possibility:
- deed (4/17) May 10 2016 Thanks. Didn't think of function returning struct with opIndex.
struct Foo { Bars bars; ... } struct Foos { Foo[] arr; Foo opIndex (size_t idx) { return arr[idx]; } ... } struct Bar { // No Car[] cars; ... } struct Bars { Bar[] arr; Bar opIndex (size_t idx) { return arr[idx]; } ... } struct Car { ... } Foos foos; Foo foo = foos[1]; // Works Bar bar = foos[1].bars[2]; // Works Car car = foos[1].bars[2].cars[3]; // Desired abstraction. For any Bar there are some Cars, but Bar doesn't hold any Cars. In other words, there could be a function Car cars (Bar bar, size_t idx) { ... }, but that would be called with parens; Car car = foos[i].bars[j].cars(k); which would be inconsistent and confusing. Defining struct Cars { Car opIndex (Bar bar, size_t idx) {} } and struct Bar { Cars cars; ... } doesn't enable chaining and then would have to be used like this, AFAIK: Car car = cars[foos[i].bars[j], k]; Which is out of the question. Any suggestions to achieve the desired abstraction in a clean manner?
May 09 2016
On Monday, 9 May 2016 at 20:14:25 UTC, deed wrote:struct Foo { Bars bars; ... } struct Foos { Foo[] arr; Foo opIndex (size_t idx) { return arr[idx]; } ... } struct Bar { // No Car[] cars; ... } struct Bars { Bar[] arr; Bar opIndex (size_t idx) { return arr[idx]; } ... } struct Car { ... } Foos foos; Foo foo = foos[1]; // Works Bar bar = foos[1].bars[2]; // Works Car car = foos[1].bars[2].cars[3]; // Desired abstraction. For any Bar there are some Cars, but Bar doesn't hold any Cars. In other words, there could be a function Car cars (Bar bar, size_t idx) { ... }, but that would be called with parens; Car car = foos[i].bars[j].cars(k); which would be inconsistent and confusing. Defining struct Cars { Car opIndex (Bar bar, size_t idx) {} } and struct Bar { Cars cars; ... } doesn't enable chaining and then would have to be used like this, AFAIK: Car car = cars[foos[i].bars[j], k]; Which is out of the question. Any suggestions to achieve the desired abstraction in a clean manner?There are lots of ways to approach this. Here's one possibility: auto cars(Bar bar) { static struct Res { Bar bar; Car opIndex(size_t i) { return /* e.g. getCar(bar, i); */ } } return Res(bar); }
May 09 2016
On Monday, 9 May 2016 at 22:33:37 UTC, John Colvin wrote:There are lots of ways to approach this. Here's one possibility: auto cars(Bar bar) { static struct Res { Bar bar; Car opIndex(size_t i) { return /* e.g. getCar(bar, i); */ } } return Res(bar); }Thanks. Didn't think of function returning struct with opIndex. Having this as opCall in a struct Cars might be a solution. What other approaches did you have in mind?
May 10 2016