July 14, 2021

On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

>

On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

>

[...]

From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators:

Postfix Operator Rewrites
op rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)

Rewriting part doesn't work with operator overloading.

If the rewriting part doesn't work with overloading then why aren't we allowed to explicitly overload post-increment/decrement operators?

How else will the OP solve their problem?

It must rewrite, otherwise it's impossible (I think).

This work:

import   std.stdio;

struct abc{
    int[100] a;

    ref int opIndex(int index)return{
        return a[index];
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}

This does work for that example but I can't return by reference because what I'm operating on is a part of an int.
Some context:

struct part_int_t(ARGS...)
{
   int _int;
   mixin(generate_parts!ARGS);
}

alias handle_t = part_int_t!("isAllocated", 1, "gen", 8, "index", 23);

handle_t handle;

static assert (is(handle.typeof_isAllocated): bool));
static assert (is(handle.typeof_gen): ubyte));
static assert (is(handle.typeof_index): uint));

handle[2] = true;
handle.gen = 1;
handle.index = 1234;

assert (handle.isAllocated);
assert (handle.gen = 1);
assert (handle[0] = 1234);

handle++;
assert (handle.index == 1235);

handle.gen++;
assert (handle.gen == 2);

handle.reset();
assert (!handle.isAllocated);
assert (handle.gen = 3);
assert (handle.index = 0);

generate_parts!ARGS produces bit masks, getters, setters, opIndex/OpAssign/Unary, etc. and it's impossible to return bits 0-26 of _int by ref.

July 14, 2021

On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote:

>

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

>

[...]

It's how the contract of post-inc/dec work---pre-inc/dec return the modified value, post-inc/dec return the original value.

[...]

That makes a lot of sense now, thank you!

July 14, 2021

On Wednesday, 14 July 2021 at 15:01:45 UTC, wjoe wrote:

>

On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

>

[...]

This work:

import   std.stdio;

struct abc{
    int[100] a;

    ref int opIndex(int index)return{
        return a[index];
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}

This does work for that example but I can't return by reference because what I'm operating on is a part of an int.
Some context:

struct part_int_t(ARGS...)
{
   int _int;
   mixin(generate_parts!ARGS);
}

alias handle_t = part_int_t!("isAllocated", 1, "gen", 8, "index", 23);

handle_t handle;

static assert (is(handle.typeof_isAllocated): bool));
static assert (is(handle.typeof_gen): ubyte));
static assert (is(handle.typeof_index): uint));

handle[2] = true;
handle.gen = 1;
handle.index = 1234;

assert (handle.isAllocated);
assert (handle.gen = 1);
assert (handle[0] = 1234);

handle++;
assert (handle.index == 1235);

handle.gen++;
assert (handle.gen == 2);

handle.reset();
assert (!handle.isAllocated);
assert (handle.gen = 3);
assert (handle.index = 0);

generate_parts!ARGS produces bit masks, getters, setters, opIndex/OpAssign/Unary, etc. and it's impossible to return bits 0-26 of _int by ref.

Try something like this:

import   std.stdio;

struct abc{
    int[100] a;

    struct Proxy{
        abc* ptr;
    	const int index;

        int opUnary(string op : "++")(){
        	return ptr.a[index];
        }
    }

    Proxy opIndex(int index)return{
        return Proxy(&this, index);
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}
July 14, 2021

On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

>

On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

>

[...]

From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators:

Postfix Operator Rewrites
op rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)

Rewriting part doesn't work with operator overloading.

If the rewriting part doesn't work with over
This work:

import   std.stdio;

struct abc{
    int[100] a;

    ref int opIndex(int index)return{
        return a[index];
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}

Oh... since it was asking for an lvalue, you just passed it by reference... seems so obvious in hindsight...

Nice.

Pity it doesn't seem to solve OP's problem.

July 14, 2021

On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote:

import   std.stdio;

struct abc{
    int[100] a;

    struct Proxy{
        abc* ptr;
    	const int index;

        int opUnary(string op : "++")(){
        	return ++ptr.a[index];     //add missing ++
        }
    }

    Proxy opIndex(int index)return{
        return Proxy(&this, index);
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}


July 14, 2021

On Wednesday, 14 July 2021 at 15:23:05 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote:

import   std.stdio;

struct abc{
    int[100] a;

    struct Proxy{
        abc* ptr;
    	const int index;

        int opUnary(string op : "++")(){
        	return ++ptr.a[index];     //add missing ++
        }
    }

    Proxy opIndex(int index)return{
        return Proxy(&this, index);
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}


The post increment still doesn't work :(

this is the output for your code:

Proxy(7FFC7ACB3E60, 0)
2

And if the add the following statements:


writeln(s[0]++);
    writeln(s[0]);
    writeln(s[0]++);
    writeln(s[0]);
    writeln(++s[0]);

Output:

Proxy(7FFCBE3CAF20, 0)
Proxy(7FFCBE3CAF20, 0)
Proxy(7FFCBE3CAF20, 0)
Proxy(7FFCBE3CAF20, 0)
3

July 14, 2021

On Wednesday, 14 July 2021 at 15:23:05 UTC, vit wrote:

>

On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote:

import   std.stdio;

struct abc{
    int[100] a;

    struct Proxy{
        abc* ptr;
    	const int index;

        int opUnary(string op : "++")(){
        	return ++ptr.a[index];     //add missing ++
        }
    }

    Proxy opIndex(int index)return{
        return Proxy(&this, index);
    }
}

void main (){
    abc s;
    s[0]++;
    ++s[0];
}


I tried changing s[0]++ to s[0] += 1

the same lvalue problem arose :(


Error: `s.opIndex(0)` is not an lvalue and cannot be modified

July 14, 2021

On Wednesday, 14 July 2021 at 15:08:56 UTC, wjoe wrote:

>

On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote:

>

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

>

[...]

It's how the contract of post-inc/dec work---pre-inc/dec return the modified value, post-inc/dec return the original value.

[...]

That makes a lot of sense now, thank you!

IT WORKS NOW

Thanks vit for the ref idea!

import   std.stdio;

struct abc{
    int[100] a;
    static int temp;
    ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE RETURN*/ {
        return a[index];
    }
    int opIndexUnary(string s)(int index)
        if(s == "++"){
        return ++a[index];
        }
    int[] opUnary(string s)() if (s == "++"){
        return a[] += 1;
    }
}

void main (){
    abc s;

    writeln(s[0]++);// doesn't work for some reason EDIT: IT NOW WORKS!!!!!!!!

    writeln(s[0]);
    writeln(++s[0]);

   // writeln(s++);//but this works!!

   // writeln(s);
}

July 14, 2021
On 7/14/21 9:13 AM, Tejas wrote:

>      ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE
> RETURN*/ {

Indeed... I cover that 'ref' here:


http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator

Two quotes from that section:

1) "it is advisable to observe the return type of the same operator on fundamental types."

NOTE: I agree that for that to make sense, one needs to know the "return type" of fundamental type operations. It may not be clear that ++i is a reference to 'i' ("i itself"):

void main() {
  int i;
  ++i = 42;
  assert(i == 42);
}

2) "With the exception of opAssign, it is recommended that the operators that modify the object return the object itself. [...] The return type is the type of the struct, marked by the ref keyword to mean reference."

Ali

July 14, 2021

On Wednesday, 14 July 2021 at 17:42:03 UTC, Ali Çehreli wrote:

>

On 7/14/21 9:13 AM, Tejas wrote:

>
 ref/*notice this ref*/ int opIndex(int

index)return/*NOTICE THE

>

RETURN*/ {

Indeed... I cover that 'ref' here:

http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator

Two quotes from that section:

  1. "it is advisable to observe the return type of the same operator on fundamental types."

NOTE: I agree that for that to make sense, one needs to know the "return type" of fundamental type operations. It may not be clear that ++i is a reference to 'i' ("i itself"):

void main() {
int i;
++i = 42;
assert(i == 42);
}

  1. "With the exception of opAssign, it is recommended that the operators that modify the object return the object itself. [...] The return type is the type of the struct, marked by the ref keyword to mean reference."

Ali

To be honest even the compiler error should have been a dead giveaway that opIndex was returning a constant value and the ++ operator can't operate on that... I should've taken the diagnostic to heart and not just tried to brute force my way through the problem.

Obviously, I retract my statement that this might be a compiler bug.