"Rick C. Hodgin" <
rick.c...@gmail.com> writes:
> On Wednesday, October 3, 2018 at 11:26:07 PM UTC-4, Ben Bacarisse wrote:
>> "Rick C. Hodgin" <
rick.c...@gmail.com> writes:
>> > Because >< is an operator. It is evaluated left-to-right as if
>> > you had used a + b + c.
>>
>> But >< is not like +. It is more like = where one side must be an
>> lvalue, except with >< both side must be. Thus (a >< b) >< c only makes
>> sense if the expression a >< b is itself an lvalue.
>
> It's an arbitrary choice. >< returns the left side, ><= returns
> the right side, but apart from moving data in two directions, it's
> otherwise identical to other operators.
I don't think you know what an lvalue is. "returns the left side" is
ambiguous in a context where you seem to be talking about ordinary
values and I am talking about lvalues.
>> You can't assign to the result of an expression that yields an ordinary
>> value (like (a + b) = c) and you should not be able to swap c with the
>> result of an expression that yields an ordinary value. That's why I
>> pointed out that a >< b should really be an lvalue expression, not an
>> ordinary one.
>
> I understand your point.
No, I really don't think you do. Can you at least see how a >< b >< c
rotates the contents of a, b and c if >< is an lvalue expression? If
not (and you certainly claimed before that it doesn't) then you are not
seeing what I am suggesting.
> I disagree. I think >< and ><= are
> special case operators, but traditional in all other ways.
I am not sure what it is you disagree with. Why, if you favour having a
swap operator, would you not want a >< b >< c to have a useful meaning?
You can still use a >< b in other expressions (since lvalues "decay" to
ordinary values).
If you also make ><= be an lvalue expression you get a ><= b ><= c being
a rotate in the other direction. What is there to disagree with here?
(By the way, if I were going to provide both operators I'd make them
mirrors of each other, for example =>< and ><=. However, I don't think
there is much value in having both.)
Here it is in C++ using << and >> for the two versions of swap. You can
do it with a swap function in C, but (a) I wanted to illustrate it with
operators, (b) in C you have to use pointers so there is no direct
analogue of the lvalue.
template <class T> class Swappable {
T content;
public:
Swappable(T v) : content(v) {}
operator T (){ return content; }
Swappable &operator<<(Swappable &s) {
T tmp = content; content = s.content; s.content = tmp;
return *this;
}
Swappable &operator>>(Swappable &s) {
T tmp = content; content = s.content; s.content = tmp;
return s;
}
};
#include <iostream>
int main()
{
Swappable<int> a = 1, b = 2, c = 3;
std::cout << a << " " << b << " " << c << "\n";
a << b << c;
std::cout << a << " " << b << " " << c << "\n";
a << b << c;
std::cout << a << " " << b << " " << c << "\n";
a << b << c;
std::cout << a << " " << b << " " << c << "\n";
a >> b >> c;
std::cout << a << " " << b << " " << c << "\n";
a >> b >> c;
std::cout << a << " " << b << " " << c << "\n";
a >> b >> c;
std::cout << a << " " << b << " " << c << "\n";
}
Do you see what I mean now?
Note that the only difference is which "side" is referenced in the
return. Note also that you get the same results, in both cases, if you
bracket the expression the "other" way: a << (b << c).
Since this is comp.lang.c, here it is in C. But with no operators and
using explicit pointers to "fake" the lvalue, it's all much less clear.
int *swapl(int *a, int *b) { int t = *a; *a = *b; *b = t; return a; }
int *swapr(int *a, int *b) { int t = *a; *a = *b; *b = t; return b; }
#include <stdio.h>
int main(void)
{
int a = 1, b = 2, c = 3;
printf("%d %d %d\n", a, b, c);
swapl(swapl(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapl(swapl(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapl(swapl(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapr(swapr(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapr(swapr(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
swapr(swapr(&a, &b), &c);
printf("%d %d %d\n", a, b, c);
}
--
Ben.