[英]Obtain a std::ostream either from std::cout or std::ofstream(file)
如何根據特定程序條件將std::ostream
綁定到std::cout
或std::ofstream
對象? 盡管由於多種原因這無效,但我想實現在語義上等同於以下內容的內容:
std::ostream out = condition ? &std::cout : std::ofstream(filename);
我見過一些不是異常安全的示例,例如來自http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html 的示例:
int main(int argc, char *argv[])
{
std::ostream* fp; //1
if (argc > 1)
fp = new std::ofstream(argv[1]); //2
else
fp = &std::cout //3
*fp << "Hello world!" << std::endl; //4
if (fp!=&std::cout)
delete fp;
}
有誰知道更好的、異常安全的解決方案?
std::streambuf * buf;
std::ofstream of;
if(!condition) {
of.open("file.txt");
buf = of.rdbuf();
} else {
buf = std::cout.rdbuf();
}
std::ostream out(buf);
這將 cout 或輸出文件流的底層流緩沖與 out 相關聯。 之后,您可以寫入“out”,它將最終到達正確的目的地。 如果你只是希望所有進入std::cout
都進入一個文件,你也可以這樣做
std::ofstream file("file.txt");
std::streambuf * old = std::cout.rdbuf(file.rdbuf());
// do here output to std::cout
std::cout.rdbuf(old); // restore
第二種方法的缺點是它不是異常安全的。 您可能想編寫一個使用 RAII 執行此操作的類:
struct opiped {
opiped(std::streambuf * buf, std::ostream & os)
:os(os), old_buf(os.rdbuf(buf)) { }
~opiped() { os.rdbuf(old_buf); }
std::ostream& os;
std::streambuf * old_buf;
};
int main() {
// or: std::filebuf of;
// of.open("file.txt", std::ios_base::out);
std::ofstream of("file.txt");
{
// or: opiped raii(&of, std::cout);
opiped raii(of.rdbuf(), std::cout);
std::cout << "going into file" << std::endl;
}
std::cout << "going on screen" << std::endl;
}
現在,無論發生什么, std::cout 都處於干凈狀態。
這是異常安全的:
void process(std::ostream &os);
int main(int argc, char *argv[]) {
std::ostream* fp = &cout;
std::ofstream fout;
if (argc > 1) {
fout.open(argv[1]);
fp = &fout;
}
process(*fp);
}
編輯:Herb Sutter 在文章Switching Streams (Guru of the Week) 中已經解決了這個問題。
std::ofstream of;
std::ostream& out = condition ? std::cout : of.open(filename);
引用自這篇文章。
您可以應用類似的方法。
struct noop {
void operator()(...) const {}
};
std::shared_ptr<std::ostream> of;
if (condition) {
of.reset(new std::ofstream(filename, std::ofstream::out));
} else {
of.reset(&std::cout, noop());
}
作為 C++ 的新手,我不知道這是否是異常安全的,但我通常這樣做:
std::ostream& output = (condition)?*(new std::ofstream(filename)):std::cout;
以下簡單代碼對我有用:
int main(int argc, char const *argv[]){
std::ofstream outF;
if (argc > 1)
{
outF = std::ofstream(argv[1], std::ofstream::out);
}
std::ostream& os = (argc > 1)? outF : std::cout;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.