初始化对istream的引用

我正在尝试编写我的程序,以便它可以处理StdIn或在命令行中指定的文件。

我通过尝试初始化一个istream的引用来引用cinifstream ,使用条件来做到这一点。

(类似的技术在这里和这里描述)

但是,当我尝试使用ifstream ,我似乎得到一个错误,即basic_istream移动构造函数被声明为protected

istream& refToCIN  ( cin );                      // This is OK
const istream& refToFile = ifstream(args[1]);    // This is OK

const istream& inStream ( FileIsProvided()? ifstream(args[1]) : cin );
// This causes error:
// std::basic_istream<char,std::char_traits<char>>::basic_istream' : 
// cannot access protected member declared in class std::basic_istream<char,std::char_traits<char>>

ProcessStream(inStream); // This could either be a file or cin

这可以通过这种方式合理地完成吗? 我忽略了一个很好的选择吗?


你的代码的问题如下:

三元运算符的左侧是一个临时(右值)。 然而,你的右手边是一个左值( cin是左值)。 因此,编译器试图从cin创建一个临时文件,并且因为复制构造函数不可用而失败。

至于sultions -你可以简单地替换rdbuf()的CIN与rdbuf()的文件,并使用cin无处不在。


这是OP提出的最终解决方案:

ifstream file;
std::streambuf* old_cin_buf = cin.rdbuf(); // Store the old value
if (FileIsProvided())
{
    file.open(args[1]);
    old_cin_buf = cin.rdbuf(file.rdbuf()); // Replace the ReadBuffer on cin.
    // Store the previous value as well.
}
// Use cin for all operations now.  It will either use the File or StdIn as appropriate.
...
// Restore the original value, in case it was changed by using a file.
cin.rdbuf(old_cin_buf); // This is better be done before file object here goes out of scope

这听起来像一个XY问题,因为你不需要这里的三元条件或参考。

作为惯例,许多程序使用-表示stdin而不是省略文件名。 这是一条可能的途径。 根据类似的思路,我会使用Boost.ProgramOptions或getopt代替手动解析命令行。 这将间接地解决您的XY问题,因为它会使FileIsProvided()函数变得冗余,并且您将通过除直接使用argv[1]之外的其他方法获得您的选项。

如果你有C ++ 11,有智能指针或std::reference_wrapper ,它允许你“重置”引用。

作为一个反动力,考虑像ostream_joiner这样的类保持一个指向其内部流对象的指针,而不是引用。 另外,我怀疑你是否喜欢不必看处理来自无害代码的悬挂引用。

除此以外...

if (FileIsProvided())
{
    std::ifstream ifs(argv[1]);
    if (ifs)
    {
        ProcessStream(ifs);
    }
} else {
    ProcessStream(std::cin);
}
链接地址: http://www.djcxy.com/p/91939.html

上一篇: Initializing reference to istream

下一篇: Java Comparator usage