重载逗号运算符*真的*会影响其操作数的评估顺序吗?

Posted

技术标签:

【中文标题】重载逗号运算符*真的*会影响其操作数的评估顺序吗?【英文标题】:Does overloading the comma operator *really* affect the order of evaluation of its operands? 【发布时间】:2011-12-10 20:39:20 【问题描述】:

逗号运算符保证从左到右的评估顺序。

[n3290: 5.18/1]:逗号运算符从左到右分组。

expression:
   assignment-expression
   expression , assignment-expression

一对用逗号分隔的表达式从左到右计算; 左边的表达式是丢弃的值表达式(第 5 条)。 每个 与左表达式相关的值计算和副作用 在每个值计算和相关的副作用之前排序 用正确的表达式。结果的类型和值是 右操作数的类型和值;结果是相同的值 类别作为它的右操作数,如果它的右操作数是一个位域 是一个glvalue和一个位域。

关于运算符的唯一其他条款没有提到评估顺序。因此,当运算符重载时,情况似乎仍然如此。

但是,再往前说,在有关表达式的一般说明中,当然指出当您重载运算符时规则会发生变化:

[n3290: 5/2]: [ 注意: 运算符可以重载,即给定 应用于类类型表达式时的含义(第 9 条)或 枚举类型(7.2)。重载运算符的使用被转换 进入函数调用,如 13.5 中所述。 重载运算符服从 第 5 章中规定的语法规则,但要求 操作数类型、值类别和评估顺序被替换为 函数调用规则。 运算符之间的关系,如++a 意思是a+=1,不保证重载运算符(13.5),并且 不保证 bool 类型的操作数。 ——尾注 ]

但是,这是non-normative 文本。是否有任何规范文本定义了这个规则,或者兼容的编译器可以忽略它吗?

【问题讨论】:

在我看来,根据Wikipedia,如果逗号运算符被重载,它只是简单地替换为函数调用,并且函数调用参数的评估顺序不依赖于实现吗?这当然意味着可以先评估右侧? @JoachimPileborg:是的,但问题是,标准中的哪个规范性段落对此进行了规定?你的想法和***都不是权威的,你只是陈述了我已经做过的事情。 ;) 啊,对不起。我应该在午餐后立即停止阅读高级问题! :) @JoachimPileborg:午餐……现在有个好主意! 只有我一个挠头想知道为什么逗号运算符可以首先被重载(而不是指定它总是返回右手操作数的类型)?或者,就此而言,想知道为什么重载“&&”和“||”被一个函数重载而不是一组函数重载,例如:“a && b”变成“fn2(temp = fn1(a)) ? fn3(temp) : fn4(temp, b))”,其中第一个fn2-fn4 的参数必须与 fn1 的返回类型匹配,并且需要的编译器临时变量将自动声明该类型? 【参考方案1】:

我手头只有 03 标准,但其中 5/3 说“第 5 条定义了运算符在应用于未重载的类型时的效果。”

因此,所有第 5 条,包括 5.18/1,仅适用于内置运算符,不适用于任何重载函数。

(不过,兼容的编译器总是可以将操作数从左到右评估为重载的operator ,()。)

【讨论】:

@edA-qamort-ora-y:大多数操作符的顺序没有指定,无论它们是否重载。仅内置, && || ?: 引入序列点。 @MikeSeymour:在 C++11 中,它们不再诱导“序列点”:-) @edA:你正在考虑跨前传。 * / 的优先级仍然高于 + -。只是多个operator, 都有相同的优先级。此外,这个问题是关于参数的评估顺序,而不是直接关于运算符调用的顺序。 @edA:优先级和评估顺序是两个不同的东西;前者是关于如何对代码中的标记进行词法解析以在编译器中形成语法树,后者是关于在运行时实际评估这些标记的顺序。 @edA-qamort-ora-y 5/2 说“重载的运算符遵守第 5 条中指定的语法规则”。

以上是关于重载逗号运算符*真的*会影响其操作数的评估顺序吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 ko 绑定中包含括号会影响评估顺序吗?为啥?

当解引用运算符 (*) 被重载时,*this 的使用会受到影响吗?

Perl中逗号运算符的执行顺序

特征顺序会影响 sklearn 中的决策树算法吗?

操作数的顺序对于 C# 中重载的 == 运算符是不是重要

我想在cpp中实现python列表,但卡在重载下标运算符[]和逗号,[关闭]