Is there an Non-Short circuited logical “and” in C++?

前端 未结 7 2114
栀梦
栀梦 2020-12-06 08:49

tl;dr: Is there a non-short circuit logical AND in C++ (similar to &&)?

I\'ve got 2 functions that I want to call, and use the return values to figure out th

相关标签:
7条回答
  • 2020-12-06 09:30

    The & operator performs logical "and" operation for bool operands and is not short circuited.

    It's not a sequence point. You cannot rely on the order of evaluation of the operands. However, it's guaranteed that both operands are evaluated.

    I do not recommend doing this. Using temporary variables is a better solution. Don't sacrifice readability for "clever code".

    0 讨论(0)
  • 2020-12-06 09:35

    If you want to use the temporary variables, but keep the return to a single statement, you could use the comma operator:

    return (b1=Func1()), (b2=Func2()), (b1&&b2);
    

    The comma operator forces a sequence point, so each one evaluates its left operand, discards the result, then evaluates its right operand.

    Another possibility, but one I'd tend to recommend against, would be for the two functions to return a type that overloads the '&&' operator. Since an overloaded operator invokes a function, it always evaluates both operands, even in cases (like &&) where the built-in operator does not -- usually that's something of a problem, but in this case it's exactly what you want:

    class mybool { 
        bool value;
    public:
        bool operator&&(mybool const &other) const { 
            return value && other.value;
        }
    };
    
    mybool Func1(int, int);
    mybool Func2(int, int);
    
    bool Func3(int x, int y, int z, int q) { 
        return Func1(x, y) && Func2(z,q);
    }
    

    While this works, it seems to me like it's just a bit too "clever" -- something that wouldn't be at all obvious to most readers. A different name for mybool might help, but offhand I can't think of one that reflects the intent very well without becoming so verbose it would be a net loss.

    0 讨论(0)
  • 2020-12-06 09:42

    A near-universal but often undocumented non-Standard operator was introduced for exactly this purpose, pioneered by GCC alongside x ?: y (x if non-zero else y), and the now sadly removed >? and <? min/max operators and their compound assignment forms (see http://gcc.gnu.org/onlinedocs/gcc/Deprecated-Features.html). Sadly, with & and && already in use, they seem to have been scraping the bottom of the barrel to find an appropriate character sequence, but that's just my opinion - would welcome any historical explanations for why this might have been chosen.

    So, while it's not currently as well known as many other operators, the >! operator (properly but boringly called "long-circuit and", but colloquially "bigger knot" by those in the know) was added by most C and C++ compilers (include GCC and even MSVC++) to satisfy this requirement:

    bool f1() { ... }
    bool f2() { ... }
    
    ...
    bool f3() { return f1() >! f2(); }
    

    Do take it for a spin ;-).

    0 讨论(0)
  • 2020-12-06 09:45

    Yes. The overloaded versions of operator&& and operator|| do not short-circuit — they evaluate both operands even if the left-hand operand "determines" the outcome... (Source)

    That being said, don't overload operator&& or operator||. Be nice to your maintenance programmers who will look at && or || and assume that they do short circuit.

    0 讨论(0)
  • 2020-12-06 09:49

    and yes, I realize that I could use temporary variables to store the returns of the two functions and then do the "short-circuit" logic on the temporary variables, but I was wondering if there was an "elegant" language solution to keep the one-line return in Func3 while still getting the logging messages from both functions.

    That would be the "elegant" solution :). Relying on the side effects of the evaluation order would be far from elegant, error prone, and hard to understand for the next developer who wanders into your project. Relying on the side effects of course contrasts with something like the following snippet, which is a completely logical and valid use case for relying on evaluation order alone:

    if ( obj != NULL && obj->foo == blah ) { /* do stuff */ }
    
    0 讨论(0)
  • 2020-12-06 09:51

    You can trivially write your own.

    bool LongCircuitAnd( bool term1, bool term2 ) { return term1 && term2; }
    
    bool Func3(int x, int y, int z, int q){
      return LongCircuitAnd( Func1(x,y), Func2(z,q) ); 
    

    And if you want to be very fancy, you could even inline it!!!

    Okay, Okay, if you really really don't want the terrible overhead of calling a function.

    bool Func3(int x, int y, int z, int q){
      return ((int)Func1(x,y)) * ((int)Func2(z,q)); 
    

    But I don't consider that elegant. It its conceivable that an overly smart compiler could short circuit this...

    0 讨论(0)
提交回复
热议问题