c++ - 有没有办法制作一个指向 std::ifstream 或 std::cin 的智能指针?

标签 c++ smart-pointers istream

我想根据某些条件从 std::ifstreamstd::cin 获取来自 istream 的输入。

就我所能使其工作而言,我必须使用原始 std::istream* 指针:

int main(int argc, char const* argv[]) {
    std::istream *in_stream;
    std::ifstream file;
    if (argc > 1) {
        std::string filename = argv[1];
        file.open(filename);
        if (not file.is_open()) {
            return -1;
        }
        in_stream = &file;
    } else {
        in_stream = &std::cin;
    }
    // do stuff with the input, regardless of the source...
}

有没有办法使用智能指针重写上面的内容?

最佳答案

智能指针不太适合这种情况,因为它需要动态分配(在这种情况下可能没有必要)


1。在另一个函数中进行处理

正如 @BoP 在评论中指出的,处理此问题的一个好方法可能是使用另一个传递适当输入流的函数:

godbolt

int do_thing(std::istream& in_stream) {
    // do stuff with the input, regardless of the source...
    int foobar;
    in_stream >> foobar;

    return 0;
}


int main(int argc, char const* argv[]) {
    std::ofstream{"/tmp/foobar"} << 1234;

    if(argc > 1) {
        std::ifstream file{argv[1]};
        if(!file) return -1;

        return do_thing(file);
    } else {
        return do_thing(std::cin);
    }
}

2.切换流缓冲区

如果您根本不会使用 std::cin 如果传递了文件名,您可以将 std::cin 的流缓冲区更改为以下之一:文件 rdbuf() - 这样您就可以在两种情况下使用 std::cin

godbolt

std::ifstream file;
std::streambuf* oldbuf = std::cin.rdbuf();
    
if (argc > 1) {
    file.open(argv[1]);
    if (!file) return -1;

    // switch buffer of std::cin
    std::cin.rdbuf(file.rdbuf());
}

// do stuff with the input, regardless of the source...
int foobar;
std::cin >> foobar; // this will reader either from std::cin or the file, depending on the current streambuffer assigned to std::cin


// restore old stream buffer
std::cin.rdbuf(oldbuf);

3.将 std::unique_ptr/std::shared_ptr 与自定义删除器结合使用

如果您仍然想使用智能指针,最简单的解决方案是使用 std::unique_ptr/std::shared_ptr 以及处理 >std::cin 案例:

godbolt

// deletes the stream only if it is not std::cin
struct istream_ptr_deleter {
    void operator()(std::istream* stream) {
        if(&std::cin == stream) return;
        delete stream;
    }
};

using istream_ptr = std::unique_ptr<std::istream, istream_ptr_deleter>;


// Example Usage:
istream_ptr in_stream;
if (argc > 1) {
    in_stream.reset(new std::ifstream(argv[1]));
    if (!*in_stream) return -1;
} else {
    in_stream.reset(&std::cin);
}

int foobar;
*in_stream >> foobar;

关于c++ - 有没有办法制作一个指向 std::ifstream 或 std::cin 的智能指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72725151/

相关文章:

c++ - 具有 shared_ptr vector 的类的析构函数导致错误

rust - 使用装箱特征对象时,Rust 的生命周期规则是什么?

c++ - Istream 最多消耗 N 个空白字符

c++ - 在 main 中将 istream 定义为全局变量

c++ - 可以使用 libcurl 将远程文件作为 istream 读取吗?

c++ - 哪种数据结构最适合实现字典?

c++ - 为什么我会出现堆栈溢出?建议将不胜感激

c++ - 单一所有者和多个引用的智能指针

c++ - 代码错误 "ld: library not found for -lmysqlclient "

c++ - 运行时计数器退出代码 139,但 gdb 使其通过