c++ - 如何在 std::ofstream 和 std::cerr 之间切换
问题描述
我想编写一个函数,该函数返回一个写入文件或 stderr 的 ostream。
我的第一次尝试:
#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;
^~~~
[...]
为什么第二个版本不起作用,实现这样的事情的正确方法是什么?
(使用 << 运算符同时写入文件和 cout是一个相关问题,但据我所知,解决方案的唯一区别是operator<<
在类外部定义的,如果我对我的代码,我仍然得到同样的错误)
解决方案
您只需要将文件流提升到全局状态。这可以是全局变量、静态成员或(我最喜欢的)块局部静态变量。这种方法确保文件流在第一次调用之前不会打开,并且在程序终止之前保持打开状态。
从那里您只需通过引用返回流。
std::ostream &get_stream() {
static std::ofstream file("somefile.txt");
return flag ? std::cerr : file;
}
推荐阅读
- node.js - IBM - 使用 API 和 Node.js 创建 VPC
- xcode - 无法在 10.15 下调试系统首选项窗格
- ruby-on-rails - 为什么当我呈现页面时,我的 simple_form_for 集合代码中不显示下拉列表项?
- azure-devops - 将父字段添加到任务板中的工作项卡
- subscription - 如何在下一个续订日期更新定期订阅价格?
- android - SDK 中的 Android 服务问题 >= 26
- javascript - JavaScript 中的动态类属性
- sql - 连接多个表以只为主表中的每条记录返回一个结果
- c# - 索引复杂对象的最快集合类型
- angular - 为什么角材料模态是透明的?