【发布时间】:2014-09-02 14:17:36
【问题描述】:
我习惯于编写小的命令行工具,它们要么接受文件名,要么从std::cin 读取,所以我使用这种模式已经有一段时间了:
int main(int argc, char* argv[])
{
std::string filename;
// args processing ...
std::ifstream ifs;
if(!filename.empty())
ifs.open(filename);
std::istream& is = ifs.is_open() ? ifs : std::cin;
std::string line;
while(std::getline(is, line))
{
// process line...
}
return 0;
}
在阅读有关 Stack Overflow 的问题后,我尝试修改我常用的模式以适应从文件或 std::istringstream 读取的需要。令我惊讶的是它不会编译并给出这个错误:
temp.cpp:164:47: error: invalid initialization of non-const reference of type ‘std::istream& {aka std::basic_istream<char>&}’ from an rvalue of type ‘void*’ std::istream& is = ifs.is_open() ? ifs : iss; // won't compile
在我看来,它正在尝试将 std::istringstream 对象 (iss) 转换为布尔值并获取其 operator void*()。
int main(int argc, char* argv[])
{
std::string filename;
std::string data;
// args processing ...
std::ifstream ifs;
std::istringstream iss;
if(!filename.empty())
ifs.open(filename);
std::istream& is = ifs.is_open() ? ifs : iss; // won't compile
std::string line;
while(std::getline(is, line))
{
// process line...
}
return 0;
}
-
为什么将
std::istringstream与std::cin和std::ifstream区别对待?它们都源自std::istream。然后我记得我已经转换了我的模式以适应三种可能性,从文件、字符串或
std::cin读取。我记得那有效(尽管它很笨拙)。因此,对这个问题应用三重解决方案,我想出了一个完全有效的软糖:int main(int argc, char* argv[]) { std::string filename; std::string data; // args processing ... std::ifstream ifs; std::istringstream iss; if(!filename.empty()) ifs.open(filename); std::istream& is = ifs.is_open() ? ifs : true ? iss : std::cin; // fudge works std::string line; while(std::getline(is, line)) { // process line... } return 0; } 为什么这个软糖有效? GCC 是否违反了关于三元运算符 (
?:) 如何解析其类型的任何规则?还是我错过了什么?
【问题讨论】:
-
错误信息与第一个程序不匹配,该代码中没有
iss。行号似乎也关闭了,除非您在main函数上方有一百多个空行。 -
@JoachimPileborg:错误消息似乎是针对第二个程序的。
-
是的,错误消息来自第二个程序。行号是关闭的,因为我从一个更大的程序中删除了所有三个示例。
-
T.C. 的回答绝对正确。答案相当简单:将三元运算符的一个(或两个)结果转换为
std:istream。
标签: c++ c++11 conditional-operator