454,913 Members | 1,263 Online Need help? Post your question and get tips & solutions from a community of 454,913 IT Pros & Developers. It's quick & easy.

 P: n/a Hi, I coded the following but It does not return what I expect, why? #include using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); // ------------------ cout << ox.i << endl; return 0; } Mar 12 '07 #1
35 Replies

 P: n/a josh a écrit : Hi, I coded the following but It does not return what I expect, why? #include using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); Because you have 5. The expression evaluates: Other ox = ( (o1 + o1) , (o3 = o2 + o1) ); Or with names Other ox = o1.operator+(o1).operator,(o3.operator=(o2.operato r+(o1))); Since o3 is 5, then o1 is also 5 and ox is 5. The reason is overloaded operator, doesn't have the same precedence as POD operator,. Is is very confusing. // ------------------ cout << ox.i << endl; return 0; } Michael Mar 12 '07 #2

 P: n/a josh wrote: Hi, I coded the following but It does not return what I expect, why? #include using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); // ------------------ cout << ox.i << endl; return 0; } I suspect that this could be undefined behaviour as the + operators have equal precedence and the order they are evaluated depends on the compiler. evaluation order is '+', '=', ',' based on precedence and hence the code is not safe. JB Mar 12 '07 #3

 P: n/a Michael DOUBEZ wrote: josh a écrit : >Hi, I coded the following but It does not return what I expect, why?#include using namespace std;class Other{public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; }};int main(){ Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); Because you have 5. The expression evaluates: Other ox = ( (o1 + o1) , (o3 = o2 + o1) ); Or with names Other ox = o1.operator+(o1).operator,(o3.operator=(o2.operato r+(o1))); Since o3 is 5, then o1 is also 5 and ox is 5. The reason is overloaded operator, doesn't have the same precedence as POD operator,. Is is very confusing. That is not the only thing confusing! Your use of operator,() is the so obfuscated! Why on Earth would you want to do something like that? What possible reason could you have? On a side note, why isn't operator,() the same precedence as the regular ',' operator? I thought that all user defined operators had the same precedence as the builtins. Adrian -- ================================================== ======== Adrian Hawryluk BSc. Computer Science ---------------------------------------------------------- Specialising in: OOD Methodologies in UML OOP Methodologies in C, C++ and more RT Embedded Programming __--------------------------------------------------__ ----- [blog: http://adrians-musings.blogspot.com/] ----- '--------------------------------------------------------' My newsgroup writings are licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 License http://creativecommons.org/licenses/by-nc-sa/3.0/ ================================================== ======== Mar 12 '07 #4

 P: n/a josh wrote: Hi, I coded the following but It does not return what I expect, why? #include using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); // ------------------ cout << ox.i << endl; return 0; } You are modifying and evaluating the same object (o1) between sequence points. Your program's behavior is therefore undefined. Please see the FAQ on ++i,i++, and following (39.15 and 39.16) http://www.parashift.com/c++-faq-lit...html#faq-39.15 Mar 12 '07 #5

 P: n/a Adrian Hawryluk a écrit : Michael DOUBEZ wrote: >josh a écrit : >>Hi, I coded the following but It does not return what I expect, why?[snip] // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); Because you have 5.The expression evaluates:Other ox = ( (o1 + o1) , (o3 = o2 + o1) );Or with namesOther ox = o1.operator+(o1).operator,(o3.operator=(o2.operato r+(o1)));Since o3 is 5, then o1 is also 5 and ox is 5.The reason is overloaded operator, doesn't have the same precedence asPOD operator,. Is is very confusing. That is not the only thing confusing! Your use of operator,() is the so obfuscated! Why on Earth would you want to do something like that? What possible reason could you have? Mostly for learning what not to do I guess. blitz++ has matrix initalisation with comma overloading. > On a side note, why isn't operator,() the same precedence as the regular ',' operator? I thought that all user defined operators had the same precedence as the builtins. Concerning the precedence, it is sloppy writing from my part: it doesn't have the same ordering properties but the precedence is kept (the lowest if I remember correctly). The point is: in POD, the comma operator is a sequence point and evaluates from left to right, the lhs of comma being discarded while when overloaded, it is just another function (no sequence point). (++i),(i*=2) is defined behavior with POD while with Operator,(): it is UB. This was the case up in the OP. Michael Mar 12 '07 #6

 P: n/a red floyd wrote: josh wrote: >Hi, I coded the following but It does not return what I expect, why?#include using namespace std;class Other{public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; }};int main(){ Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); // ------------------ cout << ox.i << endl; return 0;} You are modifying and evaluating the same object (o1) between sequence points. Your program's behavior is therefore undefined. Please see the FAQ on ++i,i++, and following (39.15 and 39.16) http://www.parashift.com/c++-faq-lit...html#faq-39.15 Further explanation: Because operator+ modifies its object **AND** you've overloaded operator, it's equivalent to calling operator,(x++,x) -- undefined behavior Mar 12 '07 #7

 P: n/a Adrian Hawryluk wrote: >The reason is overloaded operator, doesn't have the same precedence asPOD operator,. Is is very confusing. That is not the only thing confusing! Your use of operator,() is the so obfuscated! Why on Earth would you want to do something like that? What possible reason could you have? Actually, all the overloaded operators in the OP's code are doing confusing things. Mar 12 '07 #8

 P: n/a On Mar 13, 10:07 am, red floyd

 P: n/a Adrian Hawryluk wrote: Old Wolf wrote: >>To answer OP's question: the behaviour is unspecified becauseoverloaded comma operator does not retain the ordering of thebuiltin comma operator. What's happening in this case is that(o3 = o2 + o1) is being executed, and then (o1 + o1), and thenthe overloaded comma operator is called with both of those results.A different compiler might evaluate (o1 + o1) first, resulting ino5 == 6. So does that mean that the comma operator's evaluation order of left to right is not implemented correctly on the compiler? I thought that it was defined as left to right. It is, if you don't overload it. If you overload it, then the evaluation order is undefined, as I understand it. Similarly, if you overload && or ||, the "short-circuit" behavior does not occur. Mar 13 '07 #11

 P: n/a On 12 Mar, 13:16, Michael DOUBEZ using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); Because you have 5. The expression evaluates: Other ox = ( (o1 + o1) , (o3 = o2 + o1) ); Or with names Other ox = o1.operator+(o1).operator,(o3.operator=(o2.operato r+(o1))); Since o3 is 5, then o1 is also 5 and ox is 5. The reason is overloaded operator, doesn't have the same precedence as POD operator,. Is is very confusing. // ------------------ cout << ox.i << endl; return 0; } Michael so the compiler is doing: o1.operator+(01).operator,(03 = 02.operator+(01)) and evaluating it to 5 but when we define overloaded operators the rules "should" be that they have the same precedence and the same associativity and the same arity of the PDO and so really I don't understand why here the rules seems to be "could".... Here in the code it seems that it doesn't save the first evaluating operation on o1... may be only for the comma operators is there an exception rule???? Mar 13 '07 #12

 P: n/a On 12 Mar, 11:17, "josh" using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); // ------------------ cout << ox.i << endl; return 0; } the precedence, associativity and arity of overload operator, as rule, "should" be the same for the PDO but here for the comma it doesn't seem so... if I add to my class an overload of * and than I make i.e. o1 + o2 * 03 the evaluation order is correct and in fact will be FIRST o2 * o3 and SECOND o1 + (the mul result). So I think that the compiler when meet that expression will do: o1.operator+(o2.operator*(o3)) but it should do the same with: (o1.operator+(o1)).operator,(o3 = 02.operator+(o1)) so it should evaluate from left to right as the same PDO rule... so what's wrong? Mar 13 '07 #13

 P: n/a On 12 Mar, 13:16, Michael DOUBEZ using namespace std; class Other { public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; } }; int main() { Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); Because you have 5. The expression evaluates: Other ox = ( (o1 + o1) , (o3 = o2 + o1) ); Or with names Other ox = o1.operator+(o1).operator,(o3.operator=(o2.operato r+(o1))); Since o3 is 5, then o1 is also 5 and ox is 5. The reason is overloaded operator, doesn't have the same precedence as POD operator,. Is is very confusing. // ------------------ cout << ox.i << endl; return 0; } Michael the precedence, associativity and arity of overload operator, as rule, "should" be the same for the PDO but here for the comma it doesn't seem so... if I add to my class an overload of * and than I make i.e. o1 + o2 * 03 the evaluation order is correct and in fact will be FIRST o2 * o3 and SECOND o1 + (the mul result). So I think that the compiler when meet that expression will do: o1.operator+(o2.operator*(o3)) but it should do the same with: (o1.operator+(o1)).operator,(o3 = 02.operator+(o1)) so it should evaluate from left to right as the same PDO rule... so what's wrong? Mar 13 '07 #14

 P: n/a josh wrote: On 12 Mar, 11:17, "josh" Hi, I coded the following but It does not return what I expect, why?#include using namespace std;class Other{public: int i; Other(int x=1) { i = x; } Other *operator-() { return this;} Other &operator+ (Other t) { i += t.i; return *this; } Other &operator,(Other oth) { i = oth.i; return *this; }};int main(){ Other o0, o1, o2(4), o3(5); o0->i = 100; cout << o0.i << "\n" << o0->i << "\n"; // HERE it returns 5 AND not 6 WHY ??????????????????? Other ox = (o1 + o1, o3 = o2 + o1); // ------------------ cout << ox.i << endl; return 0;} the precedence, associativity and arity of overload operator, as rule, "should" be the same for the PDO but here for the comma it doesn't seem so... Precedence and arity do match. I have no idea, what you mean by associativity. Anyhow, what an overloaded comma operator lacks is the sequence point that the built-in comma operator gives you. if I add to my class an overload of * and than I make i.e. o1 + o2 * 03 the evaluation order is correct and in fact will be FIRST o2 * o3 and SECOND This is false: the evaluation order is unspecified. This is unrelated to overloading. It is unspecified for built-in types, as well. See clause [5/4]. o1 + (the mul result). So I think that the compiler when meet that expression will do: o1.operator+(o2.operator*(o3)) but it should do the same with: (o1.operator+(o1)).operator,(o3 = 02.operator+(o1)) so it should evaluate from left to right as the same PDO rule... so what's wrong? Your code has undefined behavior since it modifies the same object several times without sequence points. The overloaded comma operator does not give you the sequence point that forces left-to right evaluation. Best Kai-Uwe Bux Mar 13 '07 #15

 P: n/a On 13 Mar, 04:28, red floyd

 P: n/a BTW - What is POD? Mar 13 '07 #17

 P: n/a liam_herron wrote: BTW - What is POD? Plain Old Data. Mar 13 '07 #18

 P: n/a josh wrote: On 13 Mar, 04:28, red floyd Adrian Hawryluk wrote: >>Old Wolf wrote:To answer OP's question: the behaviour is unspecified becauseoverloaded comma operator does not retain the ordering of thebuiltin comma operator. What's happening in this case is that(o3 = o2 + o1) is being executed, and then (o1 + o1), and thenthe overloaded comma operator is called with both of those results.A different compiler might evaluate (o1 + o1) first, resulting ino5 == 6.So does that mean that the comma operator's evaluation order of left toright is not implemented correctly on the compiler? I thought that itwas defined as left to right. It is, if you don't overload it. If you overload it, then theevaluation order is undefined, as I understand it. Similarly, if youoverload && or ||, the "short-circuit" behavior does not occur. have you read it on the 14482 iso spec.? I believe so. I'm at home right now, and my copy of 14882 is at work, so it'll have to wait, unless other posters wish to comment on that. Mar 14 '07 #19

 P: n/a Precedence and arity do match. I have no idea, what you mean by associativity. when I say about associativity I mean that if we have in an expression more operators of equal precedence i.e. * / % than it will be evaluated from left-to- rigth int a = 4 / 2 * 8 -first 4/2 and SECOND 2 * 8 if I add to my class an overload of * and than I make i.e. o1 + o2 * 03 the evaluation order is correct and in fact will be FIRST o2 * o3 and SECOND This is false: the evaluation order is unspecified. This is unrelated to overloading. It is unspecified for built-in types, as well. See clause [5/4]. This is not false! the evaluation order is the same of PDO. It is unspecified only if I have in an expression the same operators i.e. int a = 4 + 6 + b + f -here is not sure that the compiler goes from left to right it is guaranted only for && !! , ?: operators Best Mar 14 '07 #20

 P: n/a red floyd a écrit : josh wrote: >On 13 Mar, 04:28, red floyd >Adrian Hawryluk wrote:Old Wolf wrote:To answer OP's question: the behaviour is unspecified becauseoverloaded comma operator does not retain the ordering of thebuiltin comma operator. What's happening in this case is that(o3 = o2 + o1) is being executed, and then (o1 + o1), and thenthe overloaded comma operator is called with both of those results.A different compiler might evaluate (o1 + o1) first, resulting ino5 == 6.So does that mean that the comma operator's evaluation order of left toright is not implemented correctly on the compiler? I thought that itwas defined as left to right.It is, if you don't overload it. If you overload it, then theevaluation order is undefined, as I understand it. Similarly, if youoverload && or ||, the "short-circuit" behavior does not occur. have you read it on the 14482 iso spec.? I believe so. I'm at home right now, and my copy of 14882 is at work, so it'll have to wait, unless other posters wish to comment on that. [1.9/18] The POD &&, ||, ?: and , define a sequence. In footnote (12) of the paragraph, it is specified that when those operators are overloaded, they designate a function and "the operand form an argument list without an implied sequence point between them". Michael Mar 14 '07 #21

 P: n/a On 14 Mar, 10:16, Michael DOUBEZ

 P: n/a josh a écrit : On 14 Mar, 10:16, Michael DOUBEZ [1.9/18] The POD &&, ||, ?: and , define a sequence.In footnote (12) of the paragraph, it is specified that when thoseoperators are overloaded, they designate a function and "the operandform an argument list without an implied sequence point between them". so when am I overloading that operators the left-to-right sequence is not implied (guaranted) and if I have i.e. a && b && c (where a,b,c are object of a Type class with that operators overloaded) is not evaluated first a && b and then the result with c ??? No. Suposing the operator&& resolves to binary function, your expression will be operator&&(operator&&(a,b),c); Then a,b and c will be evaluated in any order. Michael Mar 14 '07 #23

 P: n/a On 14 Mar, 10:51, Michael DOUBEZ

 P: n/a josh a écrit : On 14 Mar, 10:51, Michael DOUBEZ josh a écrit : >>On 14 Mar, 10:16, Michael DOUBEZ

 P: n/a josh wrote: >Precedence and arity do match. I have no idea, what you mean byassociativity. when I say about associativity I mean that if we have in an expression more operators of equal precedence i.e. * / % than it will be evaluated from left-to- rigth int a = 4 / 2 * 8 -first 4/2 and SECOND 2 * 8 I see. Note, however, that this provision does not reflect the evaluation order in terms of which subexpressions get evaluated first. E.g., a + b - c * e by left-to-right grouping for + and - is equivalent to ( a + b ) - ( c * e ) The compiler, however, is free to have c*e evaluated before a+b. if I add to my class an overload of * and than I make i.e. o1 + o2 * 03 the evaluation order is correct and in fact will be FIRST o2 * o3 and SECOND This is false: the evaluation order is unspecified. This is unrelated tooverloading. It is unspecified for built-in types, as well. See clause[5/4]. This is not false! the evaluation order is the same of PDO. It is unspecified only if I have in an expression the same operators i.e. Nope: in a*b-d/c it is unspecified whether a*b is evaluated before or after d/c. int a = 4 + 6 + b + f -here is not sure that the compiler goes from left to right it is guaranted only for && !! , ?: operators Best Kai-Uwe Bux Mar 14 '07 #26

 P: n/a Nope: in a*b-d/c it is unspecified whether a*b is evaluated before or after d/c. yes for a*b-d/c but we are speaking about more complex expressions where the order is: precedence and associativity but however I think that the comma operator when we overload it don't respect the PDO rules where is guaranted the left-to-right evaluation (as && || and ?:) Josh Mar 14 '07 #27

 P: n/a Michael DOUBEZ wrote: red floyd a écrit : [discussion on overloaded &&, ||, and ',' as sequence points redacted] >>> I believe so. I'm at home right now, and my copy of 14882 is at work,so it'll have to wait, unless other posters wish to comment on that. [1.9/18] The POD &&, ||, ?: and , define a sequence. In footnote (12) of the paragraph, it is specified that when those operators are overloaded, they designate a function and "the operand form an argument list without an implied sequence point between them". Thanks, Michael. I missed that one. I was looking at 13.6 and couldn't find it. Mar 14 '07 #28

 P: n/a josh wrote: > >Nope: in a*b-d/c it is unspecified whether a*b is evaluated before orafter d/c. yes for a*b-d/c but we are speaking about more complex expressions where the order is: precedence and associativity but however I think that the comma operator when we overload it don't respect the PDO rules where is guaranted the left-to-right evaluation (as && || and ?:) Exactly, the overloaded comma-operator differs from the comma-operator for POD types in this regard. And, I already said that: Anyhow, what an overloaded comma operator lacks is the sequence point that the built-in comma operator gives you. Best Kai-Uwe Bux Mar 14 '07 #29

 P: n/a josh wrote: >Nope: in a*b-d/c it is unspecified whether a*b is evaluated before or afterd/c. yes for a*b-d/c but we are speaking about more complex expressions where the order is: precedence and associativity but however I think that the comma operator when we overload it don't respect the PDO rules where is guaranted the left-to-right evaluation (as && || and ?:) Precedence and associativity don't define order of operations. Overloading operators changes neither of these. Overloading operators ||, &&, and , does alter their LEFT SIDE FIRST rule as well as in the case of the two formers the REQUIRED omission of the evaluation of the second operand if the first is true (for or) or false (for and). Mar 15 '07 #30

 P: n/a Precedence and associativity don't define order of operations. Overloading operators changes neither of these. No? and how the compiler could know which operations came fisrt???? it is the same algebra principles! May be I don't have understand what you want to say? Best Mar 15 '07 #31

 P: n/a In an expression a*b + c*d both multiplications have to be done before the sum can be calculated, but it is unspecified in the language whether 'a' is multiplied by 'b' first and then 'c' by 'd' or vice versa. Precedence only says that the expression a*b + c*d cannot be interpreted as a * (b+c) * d. I think your guess is ok... Mar 15 '07 #33

 P: n/a On 03/14/07, "josh" josh a écrit : >>On 14 Mar, 10:16, Michael DOUBEZ >so when am I overloading that operators the left-to-right sequence isnot implied (guaranted) andif I have i.e. a && b && c (where a,b,c are object of a Type classwith that operators overloaded) is not evaluated first a && b and thenthe result with c ??? No. Suposing the operator&& resolves to binary function, your expressionwill beoperator&&(operator&&(a,b),c);Then a,b and c will be evaluated in any order.Michael yes but the calling function operator () came before any other operator and in that case will be logic if the compiler first called operator&&(a,b) and then comapared the result with c Not necessarily. There is nothing stopping the compiler from evaluating c first, *then* evaluating operator&&(a,b). The only guarantee that we have as to the ordering of the evaluations of a, b and c is that c cannot come between a and b. These are the possible orderings: a, b, c b, a, c (b and a simultaneously), c c, a, b c, b, a c, (b and a simultaneously) -- Clark S. Cox III cl*******@gmail.com Mar 15 '07 #34

 P: n/a josh wrote: >Precedence and associativity don't define order of operations.Overloading operators changes neither of these. No? and how the compiler could know which operations came fisrt???? it is the same algebra principles! May be I don't have understand what you want to say? Precedence and associativity affect the meaning of the operators as to which operator binds to which operands. The ordering however in C++ is UNSPECIFIED other than obviously the values that are needed for later stages in the calculation have to be done earlier. However, the ones that don't matter can be done in any order. Side-effects can be applied at any time up until the sequence point. a() * b() * c() for example could execute the functions a, b, and c before it does nay of the multiples, or it could do them immediately before the value is needed... Mar 16 '07 #35

 P: n/a On Mar 16, 4:48 am, Clark Cox

### This discussion thread is closed

Replies have been disabled for this discussion. 