Thread overview
No implicit opOpAssign for structs with basic types?
Apr 04, 2020
Robert M. Münch
Apr 04, 2020
Ferhat Kurtulmuş
Apr 04, 2020
Robert M. Münch
Apr 04, 2020
Ali Çehreli
Apr 04, 2020
Robert M. Münch
Apr 04, 2020
Ferhat Kurtulmuş
Apr 04, 2020
Jonathan M Davis
April 04, 2020
D doesn't have implicit operators for structs?

struct S {float a, float b};
S a = {1, 5};
S b = {2, 5);

a += b;
Error: a is not a scalar, it is a S

So I really have to write an overloaded operator for such cases?

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

April 04, 2020
On Saturday, 4 April 2020 at 10:22:29 UTC, Robert M. Münch wrote:
> D doesn't have implicit operators for structs?
>
> struct S {float a, float b};
> S a = {1, 5};
> S b = {2, 5);
>
> a += b;
> Error: a is not a scalar, it is a S
>
> So I really have to write an overloaded operator for such cases?

Probably I didn't understand what you mean. Sorry if this is not the case, but this one is easy.
...
struct S {
    float a;
    float b;

    S opOpAssign(string op)(ref S rhs) if (op == "+"){
        this.a += rhs.a;
        this.b += rhs.b;
        return this;
    }
}


void main()
{
    S a = {1, 5};
    S b = {2, 5};

    a += b;

    writeln(a);
}
...
April 04, 2020
On 2020-04-04 10:32:32 +0000, Ferhat Kurtulmuş said:

> Probably I didn't understand what you mean. Sorry if this is not the case, but this one is easy.
> ...
> struct S {
>      float a;
>      float b;
> 
>      S opOpAssign(string op)(ref S rhs) if (op == "+"){
>          this.a += rhs.a;
>          this.b += rhs.b;
>          return this;
>      }
> }
> 
> 
> void main()
> {
>      S a = {1, 5};
>      S b = {2, 5};
> 
>      a += b;
> 
>      writeln(a);
> }
> ...

Yes, sure, but in C++ I don't have to explicitly write this down. It just works. IMO that makes a lot of sense as long as all types fit. This just looks superfluously.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

April 04, 2020
On 2020-04-04 10:32:32 +0000, Ferhat Kurtulmuş said:

> struct S {
>      float a;
>      float b;
> 
>      S opOpAssign(string op)(ref S rhs) if (op == "+"){
>          this.a += rhs.a;
>          this.b += rhs.b;
>          return this;
>      }
> }

If the struct is from some 3rd party source, how can I add such an operator overloading to it? Is it possible to "extend" a struct later?

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

April 04, 2020
On Saturday, April 4, 2020 4:22:29 AM MDT Robert M. Münch via Digitalmars-d- learn wrote:
> D doesn't have implicit operators for structs?
>
> struct S {float a, float b};
> S a = {1, 5};
> S b = {2, 5);
>
> a += b;
> Error: a is not a scalar, it is a S
>
> So I really have to write an overloaded operator for such cases?

You could just use the constructor syntax. e.g.

S a = S(1, 5);
S b = S(2, 5);

- Jonathan M Davis




April 04, 2020
On 4/4/20 8:07 AM, Robert M. Münch wrote:
> On 2020-04-04 10:32:32 +0000, Ferhat Kurtulmuş said:
> 
>> Probably I didn't understand what you mean. Sorry if this is not the case, but this one is easy.
>> ...
>> struct S {
>>      float a;
>>      float b;
>>
>>      S opOpAssign(string op)(ref S rhs) if (op == "+"){
>>          this.a += rhs.a;
>>          this.b += rhs.b;
>>          return this;
>>      }
>> }
>>
>>
>> void main()
>> {
>>      S a = {1, 5};
>>      S b = {2, 5};
>>
>>      a += b;
>>
>>      writeln(a);
>> }
>> ...
> 
> Yes, sure, but in C++ I don't have to explicitly write this down. It just works. IMO that makes a lot of sense as long as all types fit. This just looks superfluously.
> 

steves@homebuild:~$ cat test.cpp
struct S
{
	float a;
	float b;
};
int main()
{
	S a = {1, 5};
	S b = {2, 5};
	
	a += b;
}
steves@homebuild:~$ g++ -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:11:4: error: no match for ‘operator+=’ (operand types are ‘S’ and ‘S’)
  a += b;
  ~~^~~~

Doesn't seem to "just work" for me...

-Steve
April 04, 2020
On 4/4/20 8:14 AM, Robert M. Münch wrote:
> On 2020-04-04 10:32:32 +0000, Ferhat Kurtulmuş said:
> 
>> struct S {
>>      float a;
>>      float b;
>>
>>      S opOpAssign(string op)(ref S rhs) if (op == "+"){
>>          this.a += rhs.a;
>>          this.b += rhs.b;
>>          return this;
>>      }
>> }
> 
> If the struct is from some 3rd party source, how can I add such an operator overloading to it? Is it possible to "extend" a struct later?
> 

No. operators must be implemented by the type itself. That is intentional (so types always act the same no matter where you import them). The only exception is UFCS, which doesn't cover operator overloading.

However, you can make a wrapper and use alias this.

-Steve
April 04, 2020
On 4/4/20 8:45 AM, Steven Schveighoffer wrote:

>> Yes, sure, but in C++ I don't have to explicitly write this down. It
>> just works. IMO that makes a lot of sense as long as all types fit.
>> This just looks superfluously.
>>
>
> steves@homebuild:~$ cat test.cpp
> struct S
> {
>      float a;
>      float b;
> };
> int main()
> {
>      S a = {1, 5};
>      S b = {2, 5};
>
>      a += b;
> }
> steves@homebuild:~$ g++ -o test test.cpp
> test.cpp: In function ‘int main()’:
> test.cpp:11:4: error: no match for ‘operator+=’ (operand types are ‘S’
> and ‘S’)
>    a += b;
>    ~~^~~~
>
> Doesn't seem to "just work" for me...

I was about to say the same. C++ does not have this feature. What it has as a feature and as a guideline is to define an operator+ outside of the type's definition. Perhaps that's what's helping in C++ in this case: the type looks clean but there are "interface" functions outside of it.

I've used the following trick in D for many of my types, which I've been copy-pasting but it can be mixed in:

struct S {
  float a;
  float b;

  int opCmp(const(typeof(this)) that) const {
    import std.typecons : tuple;
    return tuple(this.tupleof).opCmp(tuple(that.tupleof));
  }
}

unittest {
  assert(S(3) < S(4));
  assert(S(1, 2) > S(1, 1));
}

void main() {
}

Ali


April 04, 2020
On Saturday, 4 April 2020 at 12:14:23 UTC, Robert M. Münch wrote:
> On 2020-04-04 10:32:32 +0000, Ferhat Kurtulmuş said:
>
>> struct S {
>>      float a;
>>      float b;
>> 
>>      S opOpAssign(string op)(ref S rhs) if (op == "+"){
>>          this.a += rhs.a;
>>          this.b += rhs.b;
>>          return this;
>>      }
>> }
>
> If the struct is from some 3rd party source, how can I add such an operator overloading to it? Is it possible to "extend" a struct later?

Oh I see what you mean now. In JavaScript you can for instance extend Array with an user defined method like;

Array.prototype.insert = function(index) {
    ...
    return this;
};

Of course in d CTFE helps for similar cases. But I am afraid operator overloading outside struct/class body is not available in D. It would be nice feature though.