Thread overview
Problem overloading operator for a struct with an immutable member
Mar 24, 2015
Nicolas Sicard
Mar 26, 2015
ketmar
Mar 26, 2015
ketmar
Mar 26, 2015
Jean pierre
Mar 26, 2015
ketmar
Mar 26, 2015
Nicolas Sicard
Mar 26, 2015
ketmar
Mar 26, 2015
ketmar
March 24, 2015
I don't know if this is a bug or expected behaviour. The struct is mutable, assignable and pre-increment operator works. But post-increment doesn't compile because of the immutable member.

--
struct S
{
    int i;
    immutable(Object) o;

    S opUnary(string op)() { return this; }
    void opAssign(S other) {}
}

void main()
{
    S s, t;

    t = s; // OK
    ++s; // OK
    s++; // Error: cannot modify struct s S with immutable members
}
---
March 26, 2015
On Tue, 24 Mar 2015 16:49:01 +0000, Nicolas Sicard wrote:

> I don't know if this is a bug or expected behaviour. The struct is mutable, assignable and pre-increment operator works. But post-increment doesn't compile because of the immutable member.
> 
> --
> struct S {
>      int i;
>      immutable(Object) o;
> 
>      S opUnary(string op)() { return this; }
>      void opAssign(S other) {}
> }
> 
> void main()
> {
>      S s, t;
> 
>      t = s; // OK ++s; // OK s++; // Error: cannot modify struct s S
>      with immutable members
> }

yes, this is a bug. it happens due to compiler rewrite rule (postfix operation is rewritten to expression like 'auto tmp = var; ++var; tmp', but before this compiler tries to check if `var` is modifiable lvalue.

i.e. for prefix increment compiler FIRST checks for operator overload, and only THEN checks for modifiable lvalue (if there is no overload).

but for postfix increment compiler FIRST checks for modifiable lvalue, and only THEN tries to rewrite expression and find operator overload.


March 26, 2015
On Tue, 24 Mar 2015 16:49:01 +0000, Nicolas Sicard wrote:

> I don't know if this is a bug or expected behaviour. The struct is mutable, assignable and pre-increment operator works. But post-increment doesn't compile because of the immutable member.
> 
> --
> struct S {
>      int i;
>      immutable(Object) o;
> 
>      S opUnary(string op)() { return this; }
>      void opAssign(S other) {}
> }
> 
> void main()
> {
>      S s, t;
> 
>      t = s; // OK ++s; // OK s++; // Error: cannot modify struct s S
>      with immutable members
> }
> ---

by the way. do you know that you still CAN overload postincrement operation? yes, the code is still here, and it works... somethimes. ;-)

March 26, 2015
On Thursday, 26 March 2015 at 04:57:55 UTC, ketmar wrote:
> On Tue, 24 Mar 2015 16:49:01 +0000, Nicolas Sicard wrote:
>
>> I don't know if this is a bug or expected behaviour. The struct is
>> mutable, assignable and pre-increment operator works. But post-increment
>> doesn't compile because of the immutable member.
>> 
>> --
>> struct S {
>>      int i;
>>      immutable(Object) o;
>> 
>>      S opUnary(string op)() { return this; }
>>      void opAssign(S other) {}
>> }
>> 
>> void main()
>> {
>>      S s, t;
>> 
>>      t = s; // OK ++s; // OK s++; // Error: cannot modify struct s S
>>      with immutable members
>> }
>> ---
>
> by the way. do you know that you still CAN overload postincrement
> operation? yes, the code is still here, and it works... somethimes. ;-)

There's might be a bug anyway because even with an alias this:
---
struct S
{
    int i;
    alias i this;
    immutable(Object) o;

    S opUnary(string op)() { return this; }
    void opAssign(S other) {}
}

void main()
{
    S s, t;
    auto j = s.i++; // OK
    auto i = s++; // OUCH, but we expect S.i...
}
---
March 26, 2015
On Thu, 26 Mar 2015 05:44:13 +0000, Jean pierre wrote:

>   auto i = s++; // OUCH, but we expect S.i...

but why one expecting `i` here? there IS `opUnary` overload, and `++` corretly transformed to prefix form. there is simply NO postfix form in semantically analyzed code, *all* postfix increments and decrements are transformed.

or, to say it another way, D has no postfix inc/dec operator, there are only prefix forms. postfix form it just a compiler syntactic sugar.

March 26, 2015
On Thursday, 26 March 2015 at 04:57:55 UTC, ketmar wrote:
>
> by the way. do you know that you still CAN overload postincrement
> operation? yes, the code is still here, and it works... somethimes. ;-)

Thnaks. Indeed, this works:
---
struct S
{
    int i;
    immutable(Object) o;

    void opAddAssign(int j) { i += j; }
    S opPostInc() { ++i; return this; }
    void opAssign(S other) {}
}

unittest
{
    S s;
    ++s;
    assert(s.i == 1);
    s++;
    assert(s.i == 2);
}
---

Old operator overloading to the rescue !
March 26, 2015
On Thu, 26 Mar 2015 09:02:53 +0000, Nicolas Sicard wrote:

> On Thursday, 26 March 2015 at 04:57:55 UTC, ketmar wrote:
>>
>> by the way. do you know that you still CAN overload postincrement operation? yes, the code is still here, and it works... somethimes. ;-)
> 
> Thnaks. Indeed, this works:
> ---
> struct S {
>      int i;
>      immutable(Object) o;
> 
>      void opAddAssign(int j) { i += j; }
>      S opPostInc() { ++i; return this; }
>      void opAssign(S other) {}
> }
> 
> unittest {
>      S s;
>      ++s;
>      assert(s.i == 1);
>      s++;
>      assert(s.i == 2);
> }
> ---
> 
> Old operator overloading to the rescue !

just make sure you didn't add `opUnary` there, as it will kill `opPostInc`.

it worth nothing that `opPostInc` is not deprecated yet. ;-)

March 26, 2015
On Thu, 26 Mar 2015 09:17:21 +0000, ketmar wrote:

> worth nothing
heh. my pet misspelling.