Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 21, 2013 Operator overloading question | ||||
---|---|---|---|---|
| ||||
Please refer to http://dpaste.dzfl.pl/edit/b73ef2cd The code is contrived but is trying to focus on overloading the "+" and "*" operators for a struct. Here is the output. /home/c215/c527.d(36): Error: incompatible types for ((x) + (y)): 'Arithmetic!(int)' and 'Arithmetic!(int)' /home/c215/c527.d(37): Error: 'x' is not of arithmetic type, it is a Arithmetic!(int) /home/c215/c527.d(37): Error: 'y' is not of arithmetic type, it is a Arithmetic!(int) I am trying to understand why there are errors at all. Also why the error for line 36 is different from the error for line 37. Thanks Joseph |
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Cassman | On Monday, 21 January 2013 at 06:19:47 UTC, Joseph Cassman wrote: > Please refer to http://dpaste.dzfl.pl/edit/b73ef2cd > > The code is contrived but is trying to focus on overloading the "+" and "*" operators for a struct. > > Here is the output. > > /home/c215/c527.d(36): Error: incompatible types for ((x) + (y)): 'Arithmetic!(int)' and 'Arithmetic!(int)' > /home/c215/c527.d(37): Error: 'x' is not of arithmetic type, it is a Arithmetic!(int) > /home/c215/c527.d(37): Error: 'y' is not of arithmetic type, it is a Arithmetic!(int) > > I am trying to understand why there are errors at all. > Also why the error for line 36 is different from the error for line 37. > > Thanks > > Joseph The correct keyword is "opBinary", not "opbinary". Also, that's a link to editing the paste, viewing it is: http://dpaste.1azy.net/b73ef2cd |
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nathan M. Swan | On Monday, 21 January 2013 at 06:51:23 UTC, Nathan M. Swan wrote:
> On Monday, 21 January 2013 at 06:19:47 UTC, Joseph Cassman wrote:
>> Please refer to http://dpaste.dzfl.pl/edit/b73ef2cd
>>
>> The code is contrived but is trying to focus on overloading the "+" and "*" operators for a struct.
>>
>> Here is the output.
>>
>> /home/c215/c527.d(36): Error: incompatible types for ((x) + (y)): 'Arithmetic!(int)' and 'Arithmetic!(int)'
>> /home/c215/c527.d(37): Error: 'x' is not of arithmetic type, it is a Arithmetic!(int)
>> /home/c215/c527.d(37): Error: 'y' is not of arithmetic type, it is a Arithmetic!(int)
>>
>> I am trying to understand why there are errors at all.
>> Also why the error for line 36 is different from the error for line 37.
>>
>> Thanks
>>
>> Joseph
>
> The correct keyword is "opBinary", not "opbinary". Also, that's a link to editing the paste, viewing it is:
>
> http://dpaste.1azy.net/b73ef2cd
Nice when it's an easy fix.
Appreciate the pointer on dpaste too.
Joseph
|
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nathan M. Swan | Nathan M. Swan: > The correct keyword is "opBinary", not "opbinary". The compiler must give an error message easy to understand in similar wrong cases. > http://dpaste.1azy.net/b73ef2cd This is your code: Arithmetic opbinary(string op)(Arithmetic rhs) { static if(op == "+") return add(rhs); static if(op == "*") return mul(rhs); else static assert(0, "Operator "~op~" not implemented"); } I like to add template constraints, where possible: Arithmetic opbinary(string op)(Arithmetic rhs) const pure nothrow if (op == "+" || op == "*") Bye, bearophile |
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Do you want to discuss it? :) I have noticed that phobos style guidelines favor constraints heavily over static asserts but this exactly the example when I am uneasy about such choice: static assert can both provide more user-friendly error message here and remove some code duplication.
On Monday, 21 January 2013 at 12:27:35 UTC, bearophile wrote:
> Nathan M. Swan:
>
>> The correct keyword is "opBinary", not "opbinary".
>
> The compiler must give an error message easy to understand in similar wrong cases.
>
>
>> http://dpaste.1azy.net/b73ef2cd
>
> This is your code:
>
> Arithmetic opbinary(string op)(Arithmetic rhs)
> {
> static if(op == "+") return add(rhs);
> static if(op == "*") return mul(rhs);
> else static assert(0, "Operator "~op~" not implemented");
> }
>
>
> I like to add template constraints, where possible:
>
> Arithmetic opbinary(string op)(Arithmetic rhs)
> const pure nothrow if (op == "+" || op == "*")
>
> Bye,
> bearophile
|
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to mist | On 01/21/2013 08:32 AM, mist wrote: > phobos style > guidelines favor constraints heavily over static asserts but this > exactly the example when I am uneasy about such choice: static assert > can both provide more user-friendly error message here and remove some > code duplication. Agreed but there is a problem with 'static assert' in the implementation: We don't know what user code has caused the issue. (It is a common problem in C++ templated libraries that a hard-to-understand compilation error is produced from inside a library function template.) D's template constraints move the compilation error to the exact place of the user code. void foo(string s)() if ((s == "hello") || (s == "goodbye")) { // ... } void main() { foo!"howdy"(); // <-- compilation error on this line } It is better: Error: template instance foo!("howdy") foo!("howdy") does not match template declaration foo(string s)() if (s == "hello" || s == "goodbye") To be honest, it is kind of obvious in this simple case but sometimes the cause of the error is still hard to understand even with template consraints. Ali |
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Hm, but why can't static assert provide an instantiation trace? I can live without error message but duplicating same condition twice (one time being part of implementation) hurts my eyes :(
On Monday, 21 January 2013 at 17:16:22 UTC, Ali Çehreli wrote:
> On 01/21/2013 08:32 AM, mist wrote:
>
> > phobos style
> > guidelines favor constraints heavily over static asserts but
> this
> > exactly the example when I am uneasy about such choice:
> static assert
> > can both provide more user-friendly error message here and
> remove some
> > code duplication.
>
> Agreed but there is a problem with 'static assert' in the implementation: We don't know what user code has caused the issue. (It is a common problem in C++ templated libraries that a hard-to-understand compilation error is produced from inside a library function template.)
>
> D's template constraints move the compilation error to the exact place of the user code.
>
> void foo(string s)()
> if ((s == "hello") || (s == "goodbye"))
> {
> // ...
> }
>
> void main()
> {
> foo!"howdy"(); // <-- compilation error on this line
> }
>
> It is better:
>
> Error: template instance foo!("howdy") foo!("howdy") does not match template declaration foo(string s)() if (s == "hello" || s == "goodbye")
>
> To be honest, it is kind of obvious in this simple case but sometimes the cause of the error is still hard to understand even with template consraints.
>
> Ali
|
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to mist | On 01/21/2013 10:02 AM, mist wrote: > Hm, but why can't static assert provide an instantiation trace? I can > live without error message I forgot to mention that template constraints take part in choosing the implementation as well: void foo(string s)() if ((s == "hello") || (s == "goodbye")) { // ... } void foo(string s)() if (s == "howdy") { // ... } void main() { foo!"howdy"(); // not an error: goes to special implementation foo!"merhaba"(); // error: no implementation at all } In order to achieve the same goal without template constraints we have two options: 1) Template specialization, which I don't think is not valid for non-type template parameters like string: void foo(string s == "hello")() // ERROR; I don't think possible { // ... } 2) 'static if' in the implementation: void foo(string s)() { static if ((s == "hello") || (s == "goodbye")) { // ... } else static if (s == "howdy") { // ... } else { static assert(false, "Invalid string " ~ s); } } void main() { foo!"howdy"(); foo!"merhaba"(); } You are right though, dmd does produce useful information for this simple case: Error: static assert "Invalid string merhaba" instantiated from here: foo!("merhaba") The only shortcoming that I see in this case is that the implementations for different string values are inside the same function template. > but duplicating same condition twice (one > time being part of implementation) hurts my eyes :( Can you elaborate. I don't see the duplication. Ali |
January 21, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Monday, 21 January 2013 at 18:53:08 UTC, Ali Çehreli wrote:
> ...
> Can you elaborate. I don't see the duplication.
>
> Ali
First we check that parameter is one of allowed ones in constraint. Then we do the very same check using the very same operator list to actually make a right dispatch. Looks wrong to me, we shouldn't need to.
I need to clarify though: I am perfectly aware that constraints are superior solution in many cases, especially when it comes to multiple overloads for library snippets. But exactly in given example static assert feels as better suited.
|
January 22, 2013 Re: Operator overloading question | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 01/21/2013 07:53 PM, Ali Çehreli wrote:
> ...
>
> void foo(string s == "hello")() // ERROR; I don't think possible
> {
> // ...
> }
void foo(string s : "hello")(){
// ...
}
|
Copyright © 1999-2021 by the D Language Foundation