是否存在非短路逻辑“与”?在 C++ 中?

发布于 2024-08-11 05:35:48 字数 1127 浏览 3 评论 0原文

tl;dr: C++中有非短路逻辑AND(类似于&&)吗?

我有两个要调用的函数,并使用返回值来计算出第三个复合函数的返回值。问题是我总是希望两个函数都进行评估(因为它们输出有关系统状态的日志信息)

IE:

bool Func1(int x, int y){
  if( x > y){
    cout << "ERROR- X > Y" << endl;
  }
}
bool Func2(int z, int q){
  if( q * 3 < z){
    cout << "ERROR- Q < Z/3" << endl;
  }
}
bool Func3(int x, int y, int z, int q){
  return ( Func1(x, y) && Func2(z, q) );
}

当然,函数中的条件并不那么简单,是的,我意识到我可以使用临时变量来存储两个函数的返回,然后对临时变量执行“短路”逻辑,但我想知道是否有一种“优雅”的语言解决方案可以在 Func3 中保留单行返回,同时仍然得到来自两个函数的日志消息。


回复摘要:

“按位”运算符 |和&可以用来获得效果,但前提是返回类型为 bool。我发现 ANSI C++ 规范中没有提及这一点。据我所知,这是有效的,因为“bool”被转换为 int (true = 1, false = 0),然后使用按位运算符,然后它被转换回 bool。

还可以使用运算符“+”和“*”。 ANSI C++ 规范中没有提到这一点,但可能由于与上述相同的原因而起作用。 “+”给出“或”,因为 true 被转换为 1,然后除 0 之外的任何值都被转换回 true。 “*”适用于“and”,因为 1 (true) * 0 (false) == 0(false) 和 1(true) * 1(true) == 1(true)

这两者似乎依赖于隐式类型转换为整数,然后再转换回布尔值。这两种情况都可能会让试图维护代码的人陷入困境。

其他回答归结为“仅使用临时文件”或“实现您自己的”,这不是问题所在。目标是查看 C++ 标准中是否已经实现了一个运算符来执行此操作。

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 the return value of a 3rd composite function. The issue is that I always want both functions to evaluate (as they output log information about the state of the system)

IE:

bool Func1(int x, int y){
  if( x > y){
    cout << "ERROR- X > Y" << endl;
  }
}
bool Func2(int z, int q){
  if( q * 3 < z){
    cout << "ERROR- Q < Z/3" << endl;
  }
}
bool Func3(int x, int y, int z, int q){
  return ( Func1(x, y) && Func2(z, q) );
}

Of course, the conditionals aren't quite that simple in the functions, 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.


Summary of responses:

The "bitwise" operators | and & can be used to get the effect, but only if the return type is bool. I found no mention of this in the ANSI C++ spec. From what I can tell, this works because the "bool" is converted to an int (true = 1, false = 0), and then the bitwise operator is used, then it is converted back to a bool.

The Operators "+" and "*" can also be used. This is not mentioned in the ANSI C++ Spec, but probably works because of the same reason as above. "+" give "or" because true is converted to 1, and then anything other than 0 is converted back to true. "*" works for "and" because 1 (true) * 0 (false) == 0(false) and 1(true) * 1(true) == 1(true)

Both of these seem to rely on implicit type conversion to integer and then back to bool. Both of these will likely mess up whomever tries to maintain the code.

Other responses boil down to "Just use temporaries" or "Implement your own" which was not the question. The goal was to see if there was already an operator implemented in the C++ standard to do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

素罗衫 2024-08-18 05:35:48

& 运算符对 bool 操作数执行逻辑“与”运算,并且不短路。

这不是一个序列点。您不能依赖操作数的求值顺序。但是,可以保证两个操作数都被求值。

建议这样做。使用临时变量是更好的解决方案。不要为了“聪明的代码”而牺牲可读性。

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".

最佳男配角 2024-08-18 05:35:48

是的,我意识到我可以使用临时变量来存储两个函数的返回,然后对临时变量执行“短路”逻辑,但我想知道是否有一个“优雅”的语言解决方案在 Func3 中保留单行返回,同时仍然从两个函数获取日志消息。

这将是“优雅”的解决方案:)。对于下一个进入您的项目的开发人员来说,依赖评估顺序的副作用远非优雅,容易出错,而且难以理解。当然,依赖副作用与以下代码片段形成对比,这是仅依赖评估顺序的完全逻辑且有效的用例:

if ( obj != NULL && obj->foo == blah ) { /* do stuff */ }

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 */ }
墨洒年华 2024-08-18 05:35:48

是的,有内置的运算符可以执行此操作。
+ 执行非短路 OR,* 执行 AND。

#include <iostream>
using namespace std;

void print(bool b)
{
    cout << boolalpha << b << endl;
}

int main() 
{
    print(true + false);
    print(true * false);
}

输出:

正确

Yes there are built in operators for doing this.
+ does a non short circuiting OR and * does an AND.

#include <iostream>
using namespace std;

void print(bool b)
{
    cout << boolalpha << b << endl;
}

int main() 
{
    print(true + false);
    print(true * false);
}

Output:

true

false

孤者何惧 2024-08-18 05:35:48

您可以简单地编写自己的。

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) ); 

如果你想要非常奇特,你甚至可以内联它!

好吧,好吧,如果你真的不想要调用函数的可怕开销。

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

但我不认为那么优雅。可以想象,一个过于聪明的编译器可能会短路这个......

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...

沉默的熊 2024-08-18 05:35:48

如果要使用临时变量,但将返回保留为单个语句,则可以使用逗号运算符:

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

逗号运算符强制序列点,因此每个点都会评估其左操作数,丢弃结果,然后评估其右操作数。

另一种可能性(但我倾向于建议反对)是两个函数返回一个重载“&&”的类型。操作员。由于重载运算符调用函数,因此它总是对两个操作数求值,即使在内置运算符不求值的情况下(如 &&)——通常这会产生问题,但在这种情况正是你想要的:

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);
}

虽然这有效,但在我看来,它有点太“聪明”了——这对大多数读者来说根本不明显。为 mybool 起一个不同的名称可能会有所帮助,但我想不出一个可以很好地反映意图而又不会变得如此冗长以至于造成净损失的名称。

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.

走过海棠暮 2024-08-18 05:35:48

是的。 operator&&operator|| 的重载版本不会短路 - 即使左侧操作数“确定”结果,它们也会评估两个操作数。 (来源

话虽这么说,不要重载 operator&&operator||。善待维护程序员,他们会查看 &&|| 并假设它们发生了短路。

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.

篱下浅笙歌 2024-08-18 05:35:48

正是为了这个目的,引入了一种近乎通用但通常没有记录的非标准运算符,它是由 GCC 与 x ?: y 一起开创的(x if 非零,否则 y),现在遗憾地删除了 >?min/max 运算符及其复合赋值形式(请参阅 http://gcc.gnu.org/onlinedocs/gcc/Deprecated-Features.html)。可悲的是,随着 &&& 已经在使用,他们似乎一直在刮擦桶的底部来寻找合适的字符序列,但这只是我的意见 - 欢迎任何历史解释来解释为什么会选择这个。

因此,虽然它目前不像许多其他运算符那样广为人知,但 >! 运算符(正确但无聊地称为“长电路与”,但通俗地说是“更大的结”大多数 C 和 C++ 编译器(包括 GCC 甚至 MSVC++)都添加了“由知情人士提供”来满足此要求:

bool f1() { ... }
bool f2() { ... }

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

请尝试一下;-)。

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 ;-).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文