Consider this topic a sequel of the following topic:
Previous Installment
Undefined Behavior and Sequence
Points
Let's revisit this funny and convoluted expression (the italicized phrases are taken from the above topic *smile* ):
i += ++i;
We say this invokes undefined-behavior. I presume that when say this, we implicitly assume that type of i is one of built-in types.
So my question is: what if the type of i is a user-defined type? Say it's type is Index which is defined later in this post (see below). Would it still invoke undefined-behavior?
If yes, why? Is it not equivalent to writing i.operator+=(i.operator ++()); or even syntactically simpler i.add(i.inc());? Or, do they too invoke undefined-behavior?
If no, why not? After all, the object i gets modified twice between consecutive sequence points. Please recall the rule of thumb : an expression can modify an object's value only once between consecutive "sequence points. And if i += ++i is an expression, then it must invoke undefined-behavior. If so, then it's equivalents i.operator+=(i.operator ++()); and i.add(i.inc()); must also invoke undefined-behavior which seems to be untrue! (as far as I understand)
Or, i += ++i is not an expression to begin with? If so, then what is it and what is the definition of expression?
If it's an expression, and at the same time, it's behavior is also well-defined, then it implies that number of sequence points associated with an expression somehow depends on the type of operands involved in the expression. Am I correct (even partly)?
By the way, how about this expression?
a[++i] = i; //taken from the previous topic. but here type of `i` is Index.
class Index
{
int state;
public:
Index(int s) : state(s) {}
Index& operator++()
{
state++;
return *this;
}
Index& operator+=(const Index & index)
{
state+= index.state;
return *this;
}
operator int()
{
return state;
}
Index & add(const Index & index)
{
state += index.state;
return *this;
}
Index & inc()
{
state++;
return *this;
}
};