如何使 C++ 编译器遵循与 C# 在 this 赋值语句中相同的优先级、关联性和求值顺序?

How to make the C++ compiler to follow the same precedence, associativity and order of evaluation that C# has in the this assignment statement?

考虑以下代码:

int x = 1;
int y = 2;
y = x + (x = y);

当它在 C# 中运行时,变量最终分配有这些值:

x = 2

y = 3

另一方面,当在 C++ 中运行时,变量的结尾是这样的:

x = 2

y = 4

显然,C++ 编译器使用不同的优先级关联性计算顺序比 C# 规则(如 this Eric Lippert's article 中所述)。

所以,问题是:

是否可以重写赋值语句以强制 C++ 求值与 C# 相同?

唯一的限制是将其保持为单行。我知道这可以通过将作业分成两行来重写,但目标是将它保持在一行中。

你可以这样写:

int x = 1;
int y = 2;
y = std::exchange(x,y) + y;

但非常不推荐。你甚至不得不停止浏览并思考这个简单的操作。

是的,确实有可能。

x = (y+=x) - x;

就这么简单。

Is it possible to rewrite the assignment statement to force C++ to evaluate the same as C# does?

是的。需要澄清的是,C# 中的规则是,大多数时候,表达式的左侧先于右侧进行完整计算。因此 C# 保证 + 左侧的 x 的计算发生在右侧 x = y 的副作用之前。 C++ 不作此保证;编译器可能不同意此表达式的含义。

(挑战:我说 "most" 是有原因的。举一个 C# 中的简单表达式示例,其中左侧的副作用在右侧的副作用之后执行。)

I know this can be rewritten by splitting the assignments into two separate lines

没错。您希望有一个具有两个副作用的语句:将 y 增加 x 的原始值,并将 y 的原始值赋给 x。所以你可以把它写成

int t = y;
y = y + x;
x = t;

但是:

the goal is to maintain it in a single line.

我假设 "line" 你的意思是 "statement"。美好的。只需使用逗号运算符即可。

int t = ((t = y), (y = y + x), (x = t));

简单易行。为什么你会想要,我不知道。我假设这是一个谜题,旨在引出您是否知道逗号运算符的信号。

加分项:该语句中需要多少括号?


超级奖励:如果我们不想使用逗号运算符怎么办?我们可以使用其他算子作为排序算子。

int t = ((t = y) & 0) || ((y = y + x) & 0) || (x = t);

我们执行||的左边,结果是false,所以我们执行右边,以此类推。

同样,((expr1) & 0) ? 0 : (expr2) 保证 expr1expr2 之前运行。

基本上,您在这里需要的是保证多个子表达式以特定顺序出现。查找 "sequence points" 以查看 C 和 C++ 中的哪些运算符产生序列点;您可以使用它们对表达式进行排序,因此得名。