c++ - 如何在 std::ofstream 和 std::cerr 之间切换

标签 c++ stl

我想编写一个函数,返回一个写入文件或标准错误的 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;
                    ^~~~
[...]

为什么第二个版本不起作用,实现类似功能的正确方法是什么?

( Using << operator to write to both a file and 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;
}

关于c++ - 如何在 std::ofstream 和 std::cerr 之间切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57640620/

相关文章:

c++ - 我可以依靠 std::map::operator[] 来触摸吗?

c++ - 通过在另一组上调用 erase(iterator) 从一组中删除元素。这是正常行为吗?

c++ - 深度复制链表 - O(n)

c++ - 添加索引为 -2 的整数

c++ - 如何递归删除目录?

c++ - std::map 在低内存情况下导致 "stack overflow"

c++ - 如果我将它绑定(bind)到 "this", std::bind 是否保留对象的引用/拷贝?

algorithm - 替换 `find_if`函数

c++ - 如何使用 Levenshtein 距离字符串度量

c++ - UDP 发送永远不会失败