2

I ran into an interesting line of code today. I did not know it was legal to use the word "or". I thought there was only ||. What is this called and where can I read more about it? Thanks

if (V_discount == "y" or "Y" or "Yes" or "yes")
           {
               cout << "Your discount is: ";
}

edit: It turns out the if statement doesn't do much. I put a cout<<"hi"; in the brackets, and it executes regardless of what V_discount has in it.

I thought it was called something because netbeans is highlighting "or" in blue.

2nd edit:

v == "y" || "Y" 

is not the same as

v == "y" || v == "Y"

Only the latter functions "as intended". "As intended" being checking whether v is the string "y" or v is the string "Y".

SwimBikeRun
  • 4,192
  • 11
  • 49
  • 85
  • 1
    You also can't compare strings like that. :) (unless it's of type `string`) – Mysticial Feb 14 '12 at 02:02
  • Why do you think it's called something in particular? – Nicol Bolas Feb 14 '12 at 02:02
  • 1
    @Mysticial: It wouldn't work for std::string either. The `==` part would, but the actual `or`s are pure nonsense. Or at least, not what he expects them to be. – Nicol Bolas Feb 14 '12 at 02:03
  • If he isn't including iso646.h its possible its some horrible macro that allows it to work. And if he is referring to the synonym for ||, as far as I know they're just called operator synonyms. – 0x5f3759df Feb 14 '12 at 02:04
  • @NicolBolas That's why I said "also" since it's a separate issue. – Mysticial Feb 14 '12 at 02:05
  • Did you also know that C++ provides functor objects for every logical operator (and other non-logical operators) in the language? (They are called `logical_or`, `logical_and`, `logical_not`, etc) – Seth Carnegie Feb 14 '12 at 02:05
  • Answered here: http://stackoverflow.com/questions/555505/c-alternative-tokens – Darren Engwirda Feb 14 '12 at 02:06
  • Just as a note, GCC supports these keywords out of the box, as synonyms to "||" and "&&", etc – slartibartfast Feb 14 '12 at 02:07
  • @myrkos: It's actually demanded by the standard. – Xeo Feb 14 '12 at 02:12
  • MSVC doesn't support them without a header IIRC, and I assume MSVC implements them as macros in that header. – bames53 Feb 14 '12 at 02:16
  • @bames53: MSVC (I just tried the 2010 Express version) does support the standard alternative tokens (`and`, `or`, `<%`, `%>` -- but only if you enable the `/Za` option, which the GUI describes as "Disable Language Extensions". – Keith Thompson Feb 14 '12 at 10:54

3 Answers3

7

It's called an "alternative token", documented in section 2.6 [lex.digraph] of the current ISO C++ standard, and in section 2.5 of the 1998 ISO C++ standard. (This is the same section that defines "digraphs", such as <% for { and %: for #.)

But the code you've shown uses it incorrectly.

First, if x were an int, then you'd probably want this:

if (x == 10 or x == 20 or x == 30)

rather than this:

if (x == 10 or 20 or 30)

The latter is actually legal, but it means something quite different.

And comparing strings for equality is not straightforward. If V_discount is a char* or char[], then comparing V_discount == "yes" compares pointer values, not the contents of the strings, and they'll certainly compare unequal. If V_discount is a std::string, then I think it will work -- but you still have to compare it to each of the literals individually. Otherwise, as Tony Delroy's answer says, it compiles but does something entirely unexpected involving implicit conversions to bool.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • I think you theoretically could overload `||` with a custom class to make `x == 10 or 20 or 30` "work" but I wouldn't advise it. – Chris Lutz Feb 14 '12 at 02:09
  • 2
    @Chris: [Guess what I wrote some time ago](http://ideone.com/kVngH). :> However, alas, it won't short-circuit anymore. :( – Xeo Feb 14 '12 at 02:11
  • @Xeo: in the same vein, you now have `std::all_of`, `std::any_of` and `std::none_of`. They can easily be wrapped into more interesting interfaces (shifting to ranges over iterators) to yield `if (any_of({"y", "Y", "yes", "Yes"}, V_discount))`. I quite found unfortunate that the Standard Library would only offer predicate versions, but wrapped you can add the regular value comparison easily enough. – Matthieu M. Feb 14 '12 at 07:29
2

The C++ Programming Language (page 829) just refers to them as "keywords", not giving them any special name. The C++11 standard (section 2.6) calls them "alternative token representations", but also includes e.g. <% (for {) under that name (which, I suppose, explains why it can't just call them "keywords"); I don't know if earlier standards used the same terminology.

Wikipedia calls them "operator synonyms", but that name doesn't seem to be in currency elsewhere.

ruakh
  • 175,680
  • 26
  • 273
  • 307
2

I ran into an interesting line of code today. I did not know it was legal to use the word "or". I thought there was only ||. What is this called and where can I read more about it? Thanks

It's legal. Sadly, the Microsoft Visual C++ compiler doesn't support it (at least by default - maybe there's an obscure command line switch or something). Because of the lack of portability, even people who know about them (or, and, xor) and prefer them stylistically may decide not to use them.

if (V_discount == "y" or "Y" or "Yes" or "yes") { cout << "Your discount is: "; }

"y" "Y" "Yes" and "yes" are all string literals - basically compiler-generated character arrays of the quoted text and a NUL terminator suffix (i.e. the "C" string representation, for ASCII text the ASCIIZ name is often used - Z referencing the zero/NUL value of the final byte). When these values are combined in an logical or expression, they first decay to pointers to the first character, then the pointers are quietly converted to bool values that can be ORed together. The pointers will all be non-0 values addressing the respective character buffers, and when promoting integral values to bool C++ considers any non-0 value to be true (and 0 false). So, the entire expression is equivalent to (V_discount == "y") or true or true or true. Anything or true is true, so the if statement always executes the following statement block, as you found...

edit: It turns out the if statement doesn't do much. I put a cout<<"hi"; in the brackets, and it executes regardless of what V_discount has in it.

I thought it was called something because netbeans is highlighting "or" in blue.

Editors often have a list of "keywords" significant in the languages they support, typically with various sub-categories corresponding to on-screen (or -printer) style, but that doesn't necessarily correspond to the language Standard's classifications. In C++, or is just a functionally-identifical alternative to ||, and both are called "or" or - more precisely and to differentiate them from the bitwise version - "logical or".

2nd edit:

v == "y" || "Y"  is not the same as
v == "y" || v == "Y"

Only the latter functions "as intended". "As intended" being checking whether v is the string "y" or v is the string "Y".

Generally true. If v is a user-defined type and the || operator is overloaded (replaced) by the programmer, it can actually operate "as intended", but we C++ programmers are so used to typing the second form (which works for inbuilt and Standard library value-semantic types like int and std::string) that we find having the v == "y" || "Y" "work" as per v == "y" || v == "Y" incredibly confusing, and invariable the C++ literature recommends against changing the weird but developer-familiar way of interpreting the former statement.

Note that given char v[some-number]; and candidate text in v, the above comparison would need to do the written strcmp(v, "y") or strcmp(v == "Y").

Community
  • 1
  • 1
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Didn't you mean "It's legal, sadly. The Microsoft..."? – Ben Voigt Feb 14 '12 at 03:46
  • @Ben: Not at all. ;-P. I know a lot of C++ developers shun the very thought of abandoning the C-style `||`, `&&` and `^` tokens, but having used `and`, `or` and `xor` in other languages it can "read" nicely too... I'm indifferent, but certainly don't think a compiler vendor has any business deliberately not implementing (and enabling by default) such a trivially-achievable aspect of the Standard.... – Tony Delroy Feb 14 '12 at 08:19
  • Shall we also allow `begin` and `end` instead of `{}`. It works for other languages... I'm not impressed by the ability to make C++ feel syntactically more like Basic, when the underlying semantics are so totally different. BTW, in Basic and VHDL, `Or` is equivalent to C's `|`, not `||`. Perl has both `||` and `or` with different precedence. So this actually makes matters worse. – Ben Voigt Feb 14 '12 at 13:36
  • @Ben: I'm sure the committee discussed it thoroughly, and imagine the driver must have been the same as for trigraphs (character sets and I/O devices lacking support for the usual symbols). An ugly reality all up. Regardless, a compiler vendor has no business second guessing the Standard if they're shipping what they call a "C++" compiler. – Tony Delroy Feb 15 '12 at 01:39