digitalmars.D.learn - Operator overloading question
- Joseph Cassman (15/15) Jan 20 2013 Please refer to http://dpaste.dzfl.pl/edit/b73ef2cd
- Nathan M. Swan (4/19) Jan 20 2013 The correct keyword is "opBinary", not "opbinary". Also, that's a
- Joseph Cassman (4/30) Jan 20 2013 Nice when it's an easy fix.
- bearophile (15/17) Jan 21 2013 The compiler must give an error message easy to understand in
- mist (6/23) Jan 21 2013 Do you want to discuss it? :) I have noticed that phobos style
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (23/28) Jan 21 2013 Agreed but there is a problem with 'static assert' in the
- mist (4/37) Jan 21 2013 Hm, but why can't static assert provide an instantiation trace? I
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (50/54) Jan 21 2013 I forgot to mention that template constraints take part in choosing the
- mist (9/12) Jan 21 2013 First we check that parameter is one of allowed ones in
- Timon Gehr (4/9) Jan 22 2013 void foo(string s : "hello")(){
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
Jan 20 2013
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 JosephThe correct keyword is "opBinary", not "opbinary". Also, that's a link to editing the paste, viewing it is: http://dpaste.1azy.net/b73ef2cd
Jan 20 2013
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:Nice when it's an easy fix. Appreciate the pointer on dpaste too. JosephPlease 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 JosephThe correct keyword is "opBinary", not "opbinary". Also, that's a link to editing the paste, viewing it is: http://dpaste.1azy.net/b73ef2cd
Jan 20 2013
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/b73ef2cdThis 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
Jan 21 2013
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/b73ef2cdThis 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
Jan 21 2013
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
Jan 21 2013
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 butthisexactly the example when I am uneasy about such choice:static assertcan both provide more user-friendly error message here andremove somecode 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
Jan 21 2013
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 messageI 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
Jan 21 2013
On Monday, 21 January 2013 at 18:53:08 UTC, Ali Çehreli wrote:... Can you elaborate. I don't see the duplication. AliFirst 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.
Jan 21 2013
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")(){ // ... }
Jan 22 2013