簡體   English   中英

如何在std :: ofstream和std :: cerr之間切換

[英]How to switch between std::ofstream and 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;
}

您將必須動態分配流:

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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM