我正在尝试编写我的程序,以便它可以处理StdIn或命令行中指定的文件。
我这样做的方法是尝试使用条件初始化对istream
的引用,以引用cin
或ifstream
。
但是当我尝试ifstream
时,我似乎得到一个错误,即basic_istream move-constructor被声明为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
这可以通过这种方式合理地完成吗?我有一个很好的选择吗?
答案 0 :(得分:3)
您的代码存在以下问题:
三元运算符的左侧是临时值(右值)。但是,右手边是左值(cin
是左值)。因此,编译器正在尝试创建临时的cin
,并因复制构造函数不可用而失败。
至于硫磺 - 您只需将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
答案 1 :(得分:1)
这闻起来像XY problem,因为你不需要需要三元条件或参考。
作为惯例,许多程序使用-
来表示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);
}