【发布时间】:2012-02-25 00:51:09
【问题描述】:
基本原理
我尽量避免在 C++ 代码中进行赋值完全。也就是说,我只使用初始化并尽可能将局部变量声明为const(即,始终除了循环变量或累加器)。
现在,我发现了一个不起作用的案例。我相信这是一种普遍模式,但特别是在以下情况下会出现:
问题描述
假设我有一个程序将输入文件的内容加载到字符串中。您可以通过提供文件名 (tool filename) 或使用标准输入流 (cat filename | tool) 来调用该工具。现在,如何初始化字符串?
以下操作无效:
bool const use_stdin = argc == 1;
std::string const input = slurp(use_stdin ? static_cast<std::istream&>(std::cin)
: std::ifstream(argv[1]));
为什么这不起作用?因为slurp的原型需要如下图:
std::string slurp(std::istream&);
也就是说,我的参数 non-const 因此我不能将它绑定到一个临时的。似乎也没有办法使用单独的变量来解决这个问题。
丑陋的解决方法
目前,我使用以下解决方案:
std::string input;
if (use_stdin)
input = slurp(std::cin);
else {
std::ifstream in(argv[1]);
input = slurp(in);
}
但这让我很不爽。首先,它有更多代码(在 SLOC 中),但它也使用 if 而不是(这里)更合乎逻辑的条件表达式,并且它使用声明后的赋值,这是我想避免的。
有没有避免这种间接初始化方式的好方法?这个问题很可能会泛化到需要对临时对象进行变异的所有情况。流是不是设计不当以应对这种情况(const 流没有意义,但处理临时流确实有意义)?
【问题讨论】:
-
这里为什么需要
static_cast? -
@n.m.:编译器无法看穿
?:。:两边的类型必须相同。 -
“流的设计不是很糟糕吗?”是的,非常如此。
-
@VJovic 我与这个问题并不真正相关,但它只是读取直到它到达流的末尾,并将结果存储在一个连续的字符串中。
-
我想主要的问题是 C++ 没有考虑到这种风格。在 Haskell 工具中,当传递文件名时,我通过递归函数将 stdin 替换为文件流,但我认为这在这里不合适。