据我了解,重载运算符会被编译器翻译成方法调用,例如:
stream << "test";
等同于:
stream.operator<<("test");
如果确实如此,那么为什么会导致编译错误:
#include <iostream>
#include <iomanip>
#include <ctime>
int main()
{
std::ostream s {std::cout.rdbuf()};
auto t = std::time(nullptr);
auto tm = *std::localtime(&t);
s.operator<<(std::put_time(&tm, "%H:%M:%S"));//doesn't work
return 0;
}
虽然将 doesn't work
行更改为:
s << std::put_time(&tm, "%H:%M:%S");
编译代码。
C++14 上的 GCC 和 MSVC 2017 似乎都会产生错误。这是编译器错误还是这两个语句不相等?
最佳答案
这是您的代码,但已简化:
struct X { friend void operator+(X, X); };
int main() {
X var;
var + var; // ok
var.operator+(var); // fail
}
事实是,通过显式调用 operator<<
,您依赖的事实是它确实是类的运算符(如 T& T::operator<<(const U&);
)而不是类外定义的运算符(因为如果运算符不是成员,则不能写 var.operator<<(/*...*/)
)。
如果你写var << something
,然后除了类中定义的运算符外,查找(称为 ADL)还会查找类外定义的运算符。
运算符可以在类之外定义,因为std::put_time
的返回类型指定为 ( [ext.manip] :
An object of unspecified type such that if
out
is an object of typebasic_ostream<charT, traits>
then the expressionout << put_time(tmb, fmt)
behaves as if it calledf(out, tmb, fmt)
, where the functionf
is defined as: [...]
因为需求的形式是var << var2
,没有什么可以禁止标准库实现在类之外定义它,以便使用 ADL 找到它。
关于c++ - put_time 进入流奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51832251/