为啥逗号运算符在运算符[]内部称为逗号运算符而不在运算符()内部调用?

Posted

技术标签:

【中文标题】为啥逗号运算符在运算符[]内部称为逗号运算符而不在运算符()内部调用?【英文标题】:Why is comma operator called inside operator [] but not inside operator ()?为什么逗号运算符在运算符[]内部称为逗号运算符而不在运算符()内部调用? 【发布时间】:2017-12-19 13:38:57 【问题描述】:

从前一个问题When all does comma operator not act as a comma operator? 中,我了解到函数调用中的逗号只能充当表达式分隔符。但从下面的代码来看,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() 被称为"function call operator",因为它被使用(并且解析)。 那不会使代码更具可读性,你不觉得吗? 如果operator, 的存在可以决定z(x,y) 是否有一个或两个参数,那将是令人难以置信的混乱。 @molbdnilo:这太轻描淡写了。在存在重载的情况下,您甚至不知道要考虑 哪个 f。当f 接受两个参数时,如何看待f(x,y,z) - 你是否同时尝试f(x,(y,z))f((x,y),z) 【参考方案1】:

为什么在operator[] 调用中调用逗号运算符而不在operator() 调用中调用?

如果你看grammatically,函数调用的形式是postfix-expression ( expression-listopt) . 表达式列表(这是一个initializer-list,不要与std::initializer_list 混淆)是一个comma separated list of initializer-clauses(假设至少有两个子句)。逗号被 expression-list 的解析所消耗,其中它具有特殊含义,而不是表达式的一部分。

索引的形式是 postfix-expression [ expr-or-braced-init-list ],这里没有逗号可以使用点,所以出现的任何逗号都必然是expression 的一部分。

是否有阻止编译器的特定原因,首先检查f(a,b) 不匹配任何f 声明的arity 或类型,不会尝试更改逗号状态并查看f(a.operator,(b)) 是否导致到可接受的语法?

我会选择“理智”。函数调用是程序的一个非常基本的方面,它们需要简单明了。如果您甚至不知道传递了多少个参数,那将非常容易出错。特别是如果使用内置逗号运算符,它会简单地忽略参数。

而且,强制使用逗号也很简单:add parentheses:

f(a, (t=3, t+2), c);

有三个参数,第二个的值为5

这在语法上有效,因为内部逗号不能是分隔 initializer-clause 的逗号,因为 (t=3 不是 initializer-clause

【讨论】:

除了这个想法的一般疯狂之外,你不知道你在看哪个fs,直到你知道参数(因为 ADL),如果你不知道是什么参数直到您知道存在哪些fs...

以上是关于为啥逗号运算符在运算符[]内部称为逗号运算符而不在运算符()内部调用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥编译器不能通过逗号运算符扩展可变参数模板的参数?

为啥以下代码中逗号运算符的工作方式有所不同?

c语言这个逗号表达式的结果是啥,为啥?

C逗号表达式

逗号表达式

c语言逗号表达式