operator>>(,) 重载以一种令人惊讶的方式表现
operator>>(,) overload behaving in a surprising way
嗯,也许这并不奇怪。 Whosebug 对此有很多问题和贡献。只是他们不完全是重点。
这里是 C++ 标准的摘录(实际上是 c++14 草案,但我假设这段话在当前的 C++11 标准中是相同的):
An operator function shall either be a non-static member function or be a non-member function that has
at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an
enumeration. It is not possible to change the precedence, grouping, or number of operands of operators.
The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for
specific class and enumeration types by defining operator functions that implement these operators. Operator
functions are inherited in the same manner as other base class functions.
因此,根据我的理解,将 1 个 class 类型和一个非 class 类型作为 operator>>(,) 的参数是完全合法的。标准没有说 "The first" 或 "The second" 参数。只有 "One" 个必须是 class 类型。
这是一个令我惊讶的代码片段:
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; :
}
请注意,"A function pointer is not a class type" 虽然是正确的陈述,但并不是一个全面的答案。正如您在以 int x = ...
开头的重写代码和 operator>> 第二个参数的定义中所见,函数指针被静默转换为 std::function.
我在标准的任何地方都找不到一段说明这两个(据称)同义形式的转换规则不同的段落。
那么,这是编译器错误、社区范围内对 C++ 规范的过度解释还是……我们在这里看到的其他问题?或者只是我的一些愚蠢的疏忽?
但是"A function pointer is not a class type"是正确答案。
第13.6条中有如下注释:
operator overload resolution occurs only when an operand expression originally has class
or enumeration type
规范规则在13.3.1.2(强调我的):
If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to Clause 5.
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 11.
仅当其中一个操作数是 class 类型时,这些形式才是同义词。由于两者都不在此处,因此不会重写为 operator>>()
。
嗯,也许这并不奇怪。 Whosebug 对此有很多问题和贡献。只是他们不完全是重点。
这里是 C++ 标准的摘录(实际上是 c++14 草案,但我假设这段话在当前的 C++11 标准中是相同的):
An operator function shall either be a non-static member function or be a non-member function that has at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration. It is not possible to change the precedence, grouping, or number of operands of operators. The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific class and enumeration types by defining operator functions that implement these operators. Operator functions are inherited in the same manner as other base class functions.
因此,根据我的理解,将 1 个 class 类型和一个非 class 类型作为 operator>>(,) 的参数是完全合法的。标准没有说 "The first" 或 "The second" 参数。只有 "One" 个必须是 class 类型。
这是一个令我惊讶的代码片段:
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; :
}
请注意,"A function pointer is not a class type" 虽然是正确的陈述,但并不是一个全面的答案。正如您在以 int x = ...
开头的重写代码和 operator>> 第二个参数的定义中所见,函数指针被静默转换为 std::function.
我在标准的任何地方都找不到一段说明这两个(据称)同义形式的转换规则不同的段落。
那么,这是编译器错误、社区范围内对 C++ 规范的过度解释还是……我们在这里看到的其他问题?或者只是我的一些愚蠢的疏忽?
但是"A function pointer is not a class type"是正确答案。
第13.6条中有如下注释:
operator overload resolution occurs only when an operand expression originally has class or enumeration type
规范规则在13.3.1.2(强调我的):
If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to Clause 5.
If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator. Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 11.
仅当其中一个操作数是 class 类型时,这些形式才是同义词。由于两者都不在此处,因此不会重写为 operator>>()
。