14

Possible Duplicates:
&&= and ||= operators

See title. This question may be expanded to include all logical+assignment operators. To clarify: I am not talking about |= operator.

Another example: &&=

Thanks.

Example:

bool result = false;

// Today
result = result || my_test1();
// Do stuff
result = result || my_test2();

// In my imagination only...
result ||= my_test1();
// Do stuff
result ||= my_test2();
Community
  • 1
  • 1
kevinarpe
  • 20,319
  • 26
  • 127
  • 154
  • What exactly would be the use case for such an operator? – RedX Jul 13 '11 at 08:32
  • There _are_ operators for such a (rarely, if ever, needed) construct. The syntax is `|=!!` and `&=!!`, respectively. Whether that's code you would like to write is a different question (though admittedly I've used at least the `!!` idiom a few times before, and the `likely` macro in the Linux kernel sources uses it as well). – Damon Jul 13 '11 at 08:39
  • 8
    @Damon: `|=!!` isn't a operator, its a combination of three operators: `|= ! !` and the high precedence of the `!` leads to problems if you have a expression with lower precedence, like `+` on the right side, e. g. `x |=!! 5 + x` will give you `x |= 1+x`. – Gunther Piez Jul 13 '11 at 08:46
  • @drhirsch: Yes I'm well aware that it's not a single operator, though the combination of operators does what the question (before the edit) asked in one possible interpretation. As I wrote above, it's not something one would probably want to use (though not so much because of precedence issues but rather because it may not be immediately obvious to soemone else what's intended). It's a bit like the style in the rather well-known "russian rangecoder". – Damon Jul 13 '11 at 08:55
  • 3
    @Damon It also won't have the lazy evaluation of the || operator, which is quite significant. – Adam Bowen Jul 13 '11 at 09:19
  • @Suma: Your possible duplicate is about Java not C. – JeremyP Jul 13 '11 at 11:00
  • Related: https://stackoverflow.com/questions/2488406/why-doesnt-c-have-or-for-booleans – Daniel Chin Jul 26 '23 at 12:19

4 Answers4

16

At a guess, as they would only make sense for bools, which were late to the party

Even if bools had been around at the start these operators would be of limited use, as without side-effects they would be identical to |= and &= with boolean operands, so the only use would be trapping passing a non-bool in by accident.

If the proposed operators are also short-circuiting (not unreasonable as || and && are for in-built types) then you also have an additional justification for them in the presence of side effects.

The only other possible reason I can think of for allowing them would be if it significantly simplified parsing/compiling the language, however that is likely not the case given that they don't make sense for non-bool types.

Ultimately they are not in the language because no one has cared enough to put them in the language, thus we can conclude that none of these justifications is sufficient to warrant the cost of submitting a proposal, getting it into the standard and implementing the feature.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
jk.
  • 13,817
  • 5
  • 37
  • 50
  • 8
    "as they would be identical to |= and &=" no they would not be the same. bool a = true; a ||=somecomplexfuncReturningBoolAfterAnHour() – josefx Jul 13 '11 at 09:16
  • "the only use would be trapping passing a non-bool in by accident"... that implies that use isn't sufficient justification, but IMHO it is sufficient. Further, you've missed the fact that && and || are short-circuit operations, and if the language provided short-circuit `||=` and `&&=` they would be potentially more efficient - and usable despite potential null-pointer issues etc - than absuing `|=` and `&=` for the same code. – Tony Delroy Jul 13 '11 at 09:28
  • 3
    Would have upvoted, if the answer had consisted of the first sentence only. `&&=` makes as much sense as `&&`: `3 && 4` is true, whereas `3 & 4` is false. – soulmerge Jul 13 '11 at 10:50
  • -1 `||=` would not be equivalent to `|=`. The result of `||` is **only** 1 or 0 (C99 6.5.14). – JeremyP Jul 13 '11 at 11:08
  • @JeremyP hence qualifying it for boolean operands – jk. Jul 13 '11 at 19:56
  • @jk: it's still legal to use && and || for integer operands and assign the result to an integer. `int a = 27 ; a = a && b;` is legal. So `a &&= b;` would theoretically also be legal if the operator existed. – JeremyP Jul 14 '11 at 12:43
8

Because they wouldn't make sense. The definition of x op= y is x = x op y, except that x is only evaluated once. What does this mean with a short circuited operator, which converts each of its operands (if it evaluates them) to bool? The equivalent of ||= might be something like:

if ( !x )
    x = y;

which is certainly different from the interpretation of other op=.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • You've practically countered your opening statement! :-) Short-circuit operation of builtins is a keen observation, and your proposed equivalent make senses to me for builtin types. In keeping with C++ behaviour for user-defined types, you'd expect explicitly user-defined `operator&&=(bool rhs)` not to be short circuit. It's all a smidge weird, but is in keeping with what C++ does now... if it were proposed for a future C++ Standard, I can't imagine anyone seriously objecting that it "wouldn't make sense". – Tony Delroy Jul 13 '11 at 08:56
  • @Tony Propose it, then. My opening statement may have been too general: op= operators can't make the same sense as conventional op= operators; the definition for them would have to be different if we want to maintain short-circuiting. (On the other hand, user defined `||` and `&&` don't short-circuit, so there is some precedent for dropping it. Bad precedent, IMHO.) – James Kanze Jul 13 '11 at 09:03
  • 1
    My reasoning (no matter if x is evaluated once *if possible* or no) would be that since "a = a && b" is perfectly thinkable and usable, then "a &&= b" could be given too; thus I think it's just because they are "late" as another user answered. – ShinTakezou Jul 13 '11 at 09:06
  • @James: "Bad precedent"... which perhaps suggests a more interesting and radical proposal... that classes be able to define a function e.g. `bool operator&&() const` / `bool operator||() const` which indicates whether they should short-circuit: the compiler could arrange a call to that before evaluating the argument for `bool operator&&(...rhs) const`. Seems backwards compatible too. – Tony Delroy Jul 13 '11 at 09:08
  • @Shin Takezou They aren't late; `||` and `&&` have existed since the very early days of C. The reason (I'm almost sure) is because op= is defined as x = x op y, and this definition doesn't make too much sense for short-circuiting operators. – James Kanze Jul 13 '11 at 10:05
  • I disagree with "wouldn't make sense", yet this is my favorite answer overall. C has no short-circuiting assignments, and if they existed, they'd basically be shorthand "hidden" conditionals, much easier to fail to notice than an explicit `if`. You can make similar arguments for `&&` etc, but maybe there's a stronger case for usefulness/convenience outweighing oddity. –  Jul 13 '11 at 10:50
  • I would like a construct like "a ||= b" where a stays true and b will be ignored when a is true, otherwise a will get the boolean value of b (and b evaluated), and "similar" for a &&= b. I do not see any reason not to allow this (or, to stay on the opposite side, I could say I see no reason to have OP=, or even -- ++) – ShinTakezou Jul 13 '11 at 12:45
  • @ShinTakezou I understand what you want. In my opinion, it's not unreasonable; at any rate, it's more reasonable than being able to overload `&&` and `||`. But it does mean defining a different semantic for the op= than for the others, and nobody ever made a proposal (to my knowledge, at least) in this direction. – James Kanze Jul 13 '11 at 16:23
5

No good logical reason... just historical pressures for features.

Logical operators aren't normally available as single CPU opcodes, so they're not as cheap or fundamental as their bitwise counterparts. A logical XOR would be nice too, perhaps ^^, then ^^=.

Still, a proliferation of operators makes it increasingly painful to create drop-in user-defined types with builtin-style semantics, and there's little real-world gain. I'd still like to see them - these operators do exist in some other languages, like Ruby, and I've found them convenient and expressive.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • 1
    +1 the "no good logical reason..." seems to me the most logical explanation, though the tracking back to CPU opcodes do not convince me totally (cpus may have a "set on condition" and bitwise operators on integers that are just 1 or 0 behave like logical operators) – ShinTakezou Jul 13 '11 at 09:18
  • @ShinTakezou: "set on condition" can facilitate in mapping from integers to booleans, but if you have two registers or memory location with integers and need to first "test" them to set the conditions then use that condition to generate a "standard" 0 versus 1 boolean value, then apply the bitwise operator - you've got more steps. Something akin to `or regA, regA // sets conditions; set0ifz_1ifnz regA;` before you can do a bitwise operation. The "set0ifz_1ifnz" might not be available as a single opcode either. – Tony Delroy Jul 13 '11 at 09:38
  • I agree, but I also suppose these "limits" of the cpus can't affect nowadays syntax of modern languages, if one see useful to have such a syntax, of course; compilers then may optimize heavily the produced code, no matter how the source looks (e.g. "a++" of C against "a = a + 1" of other languages can produce the same code) – ShinTakezou Jul 13 '11 at 12:48
3

Because their modus operandi is widely different.

Look at the signatures:

T operator+(T,T);
T& T::operator+=(T);

T operator*(T,T);
T& T::operator*=(T);

bool operator&&(T,T);
???

Compounds operators exist for operators that return the same type of argument, the && and || operators return a boolean (or at least, are expected to), and therefore it does not make sense to create a compound version, except perhaps for booleans only.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • I've never tried this, but I suppose also "floatA & floatB" does not have much sense, though the result can be, formally, a floatC; moreover especially in C where there's no primitive bool type, and we can use an int for it; so if "doubleA &= floatB" is possible, even "a &&= b" should be, I think. – ShinTakezou Jul 13 '11 at 09:14
  • "`&&, || and ^` operators return a boolean"... nope, `^` is a bitwise operator, that this isn't universally known might be because they can be applied to booleans with some success, though it's risky. Further, this assumes you're talking about C++ overloading, but doesn't discuss why the C and C++ compilers don't provide those operations for actual builtin booleans. – Tony Delroy Jul 13 '11 at 09:20
  • @ShinTakezou: There is not `bool` but about everyone has a `Bool` typedef'ed and there is a notion of Boolean Context for conditions @Tony: right for `^`, I slipped. I was not talking (not really) about operator overloading, I just needed to expose signatures to show the difference. – Matthieu M. Jul 13 '11 at 09:39
  • @Matthieu && @Shin: C99 now has a boolean primitive type. – JeremyP Jul 13 '11 at 11:13
  • In fact I'm used to include stdbool.h and use bool as primitive type; formally I expect "t && a" resulting in a bool where the Boolean Context is given by the && itself. In C, "a = a && b" where a and b are both int, is ok. So, I meant, we don't need the "boolean only" constraint. – ShinTakezou Jul 13 '11 at 12:27