【发布时间】:2019-08-24 18:34:05
【问题描述】:
我想编写一个函数,该函数返回一个 ostream,该 ostream 可以写入文件或 stderr。
我的第一次尝试:
#include <fstream>
#include <iostream>
std::ostream get_stream() {
bool flag = (time(nullptr) % 2); // stand-in
if (flag)
return std::cerr;
else
return std::ofstream{"somefile.txt"};
}
int main() {
auto logger {get_stream()};
logger << "Just testing, everything is fine."
<< std::endl;
}
这会因(长)编译器错误而失败 - 我怀疑是因为 std::cerr 没有复制构造函数。另一个变体(返回引用)不起作用,因为 ofstream 是一个局部变量。我可以在堆上分配ofstream,但是调用者不知道是否需要释放指针(当我们返回对std:cerr 的引用时它不会)。
所以,我写了第 2 版:
#include <fstream>
#include <iostream>
struct Logger {
std::ofstream ostream;
bool to_stderr {true};
template<typename A>
Logger& operator<<(A rhs) {
if (to_stderr)
std::cerr << rhs;
else
ostream << rhs;
return this;
}
};
int main() {
Logger logger;
logger << "Just testing, everything is fine."
<< std::endl;
}
这也会失败,并出现以以下开头的长编译错误:
$ g++ -Wall -o v2 v2.cpp
v2.cpp: In function ‘int main()’:
v2.cpp:30:12: error: no match for ‘operator<<’ (operand types are ‘Logger’ and ‘<unresolved overloaded function type>’)
logger << "Just testing, everything is fine."
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<< std::endl;
^~~~~~
v2.cpp:9:13: note: candidate: template<class A> Logger& Logger::operator<<(A)
Logger& operator<<(A rhs) {
^~~~~~~~
v2.cpp:9:13: note: template argument deduction/substitution failed:
v2.cpp:30:20: note: couldn't deduce template parameter ‘A’
<< std::endl;
^~~~
[...]
为什么第二个版本不工作,实现这样的事情的正确方法是什么?
(Using << operator to write to both a file and cout 是一个相关问题,但据我所知,解决方案的唯一区别是operator<< 是在类外部定义的,如果我对我的代码进行相同的更改,我'我仍然得到同样的错误)
【问题讨论】:
-
您不能按值传递或返回流。
-
如果
get_stream()返回std::ostream&,第一个将起作用。 -
@PeteBecker 返回引用修复了我们想要返回
cerr的情况,但它破坏了返回文件流,因为这是一个局部变量。 -
@Nikratio - 所以不要让它成为局部变量。