如何在 std::ofstream 和 std::cerr 之间切换
How to switch between std::ofstream and std::cerr
我想写一个函数,返回一个写入文件或标准码流的函数。
我的第一次尝试:
#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::unique_ptr<std::ostream> get_stream() {
bool flag = time(0) % 2;
return ( flag
? std::make_unique<std::ostream>(std::cerr.rdbuf())
: std::make_unique<std::ofstream>("somefile.txt")
);
}
int main() {
auto logger {get_stream()};
*logger << "Just testing, everything is fine."
<< std::endl;
}
您只需要将文件流提升为全局状态。这可以是全局变量、静态成员或(我最喜欢的)块局部静态变量。此方法可确保文件流在首次调用之前不会打开,并且在程序终止之前将保持打开状态。
从那里,您只需通过引用返回流。
std::ostream &get_stream() {
static std::ofstream file("somefile.txt");
return flag ? std::cerr : file;
}
相关文章:
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- std::is_convertible 和 std::convertible_to 之间的区别(在实践中)?
- std::filesystem 和 std::experimental::filesystem 之间的路径差异
- 在什么条件下使用 std::memcpy 在对象之间复制是安全的?
- std::memmove在同一对象之间是否始终安全
- Cxx.jl 在 Julia Complex 和 std::complex 之间进行转换
- 如何在 std::string 和 Aws::String 之间进行转换?
- std::weak_ptr 和相应的 std::shared_ptr 之间是否存在数据竞争?
- std::fabs(a * b) 和 std::fabs(a) * std::fabs(b) 之间的区别
- 如何在窗口之间移动 std::unique_ptr 而不会冒内存泄漏的风险?
- 简单使用 std::atomic 在两个线程之间共享数据
- "+=" 操作在类型之间不起作用 std::复杂<double>和__complex__双精度
- "std::function<double(double)>"到"double (*)(double)"之间的转换
- malloc 和 calloc 与 std::string 之间的区别
- std::random_device和std::mt19937_64之间有什么区别
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 我收到void main()和使用命名空间std;之间的冲突;?我正在使用代码块
- iostream和命名空间std之间的关系是什么?