运算符>>(,)重载以令人惊讶的方式运行

时间:2015-01-07 19:09:07

标签: c++ overloading

嗯,也许这并不令人惊讶。 Stackoverflow在这一点上有很多问题和贡献。只有它们并不完全正确。

这里是C ++标准的摘录(实际上是c ++ 14草案,但我认为这段经文在当前的C ++ 11标准中是相同的):

  

运算符函数应该是非静态成员函数或者是非成员函数   至少一个参数,其类型是类,对类的引用,枚举或对引用的引用   列举。无法更改运算符的优先级,分组或操作数。   可以更改为每种类型预定义的运算符=,(一元)&和(逗号)的含义   通过定义实现这些运算符的运算符函数来定义特定类和枚举类型。操作者   函数的继承方式与其他基类函数相同。

因此,据我所知,将1类类型和一类非类型作为参数运算符>>(,)是完全合法的。该标准没有说“第一个”或“第二个”参数。其中只有“一个”必须是班级类型。

这是一个令我惊讶的代码片段:

int operator>> ( int v, std::function<int(int)> transformer )
{
    int v1 = transformer(v);
    DGS::CLogger::GetLogger()->Log<int>(&IntFormatter, v1 );
    return v1;
}
static int DoItLoggedAndCompact( int value )
{
    int x = operator>>( operator>>(value, DoIt) , AnotherIntCalculation ); // compiles and works!
    return x;
// The following line produces (with clang++):
// error: invalid operands to binary expression ('int' and 'int (*)(int)')
//      return value >> DoIt >> AnotherIntCalculation; : 
}

请注意“函数指针不是类类型”,而作为正确的语句,并不是一个全面的答案。正如您在以int x = ...开头的重写代码和运算符&gt;&gt;的定义中看到的那样第二个参数,函数指针静默转换为std :: function。

我无法在标准中的任何地方找到一条说明这两个(据称)同义形式的转换规则不同的段落。

那么,这是一个编译器错误,社区范围内对C ++规范的过度解释还是......我们在这里看到的其他东西?或者只是我的一些愚蠢的疏忽?

1 个答案:

答案 0 :(得分:6)

“函数指针不是类类型” 正确答案。

第13.6条中有以下注释:

  仅当操作数表达式最初具有类时,才会发生

运算符重载决策   或枚举类型

规范性规则见13.3.1.2(强调我的):

  

如果表达式中的运算符的操作数没有类型或枚举类型,则假定运算符是内置运算符,并根据第5章进行解释。

     

如果任一操作数的类型是类或枚举,则可能会声明用户定义的运算符函数来实现此运算符,或者转换操作数可能需要用户定义的转换到适合内置运算符的类型。在这种情况下,重载决策用于确定调用哪个运算符函数或内置运算符来实现运算符。因此,运算符表示法首先转换为等效的函数调用符号,如表11所示。

仅当其中一个操作数是类类型时,表单才是同义词。由于这两个都不在,所以不会重写为operator>>()