从所有逗号操作员不充当逗号操作员时,我就知道函数呼叫中的逗号只能充当表达sperator。但是从下面的代码看来,operator()
的行为与函数调用一样,而operator[]
则没有。
所以我有两个问题:
- 为什么逗号操作员在
operator[]
呼叫中而不是在operator()
呼叫中打电话? - 是否有特定原因阻止编译器,首先检查
f(a,b)
是否与任何F声明的ARITY或类型不匹配,不会尝试更改逗号状态并查看f(a.operator,(b))
是否导致可接受的合成?从我的角度来看,这将是类型转换带来的过程。
代码示例:
struct A{ };
struct B {
A operator,(const B & other) const { return A(); }
};
struct C {
C(){}
C(const A & a){}
void operator[](const A & a) const {}
void operator()(const A & a) const {}
};
void f(const A & a){}
int main()
{
B x,y;
C z;
//these do no compile because ',' in a function call is an argument separator
//C(x,y);
//f(x,y);
//but this one compiles as z[x.operator,(y)]
z[x,y];
//and this one does not
//z(x,y);
//finally all of these do compile
z((x,y));
C((x,y));
f((x,y));
return 0;
}
为什么逗号操作员在
operator[]
呼叫内而不是在operator()
呼叫中打电话?
如果您以语法的形式看,函数调用是 postfix-expression (
expression-list opt )
。 expression-list (这是 initunizer-list ,不要与 std::initializer_list
混淆)是逗号分隔列表(假设至少有两个子句)。逗号是通过具有特殊含义的表达列表的解析而不是表达式的一部分来消耗的。
索引为 postfix-expression [
expr-or-braced-init-list ]
,此时尚无逗号,因此任何逗号出现的逗号必定是表达的一部分。
是否有特定原因阻止编译器,首先检查
f(a,b)
是否与任何f
声明的ARITY或类型不匹配,不会尝试更改逗号状态并查看f(a.operator,(b))
是否导致可接受的语法?/p>
我要去"理智"。功能调用是程序的真正基本方面,它们需要直接。如果您甚至不知道您通过了多少个参数,那将是非常容易出错的。特别是如果使用了内置逗号运算符,这只是忽略了参数。
此外,强制使用逗号非常简单:添加括号:
f(a, (t=3, t+2), c);
有三个参数,其中第二个具有值
5
。
这是语法作用的,因为内部逗号不能是分隔 initializer-clause-clause s的逗号,因为 (t=3
不是 inatimerizer-clause-clause 。。。
问题并回答说明 []
订阅中逗号的行为,正确地写下了逗号。
但是,对于当前和未来的读者:
使用C 20,将,
直接在[]
中使用。现在应该对其进行括号,这意味着代替z[x,y]
应该使用z[(x,y)]
。逗号仍被解释为operator,
(或内置逗号操作员),但无论哪种情况下)。
使用C 23 z[x,y]
中逗号的含义(无括号)将会改变。现在,它将被解释为operator[](x,y)
,而不是operator[](operator,(x,y))
,就像z(x,y)
始终被解释为operator()(x,y)
一样。以前operator[]
只能有一个参数。使用C 23,它将被允许具有与operator()
相同的多个参数。
这是语言的破坏性变化,尽管[]
下标中使用逗号运算符几乎没有实际用途,并且可能令人惊讶/无意间行为,因为鉴于()
的差异和看似多维的索引性质。