我正在构建一个 PromptSet
可以连续提出一系列问题。出于测试原因,它允许您传递读取器和写入器,而不是直接使用标准输入和标准输出。
因为 stdin 和 stdout 是常见的用例,我想创建一个默认的“构造函数”,允许用户生成 PromptSet<StdinLock, StdoutLock>
无需任何参数。到目前为止,这是代码:
use std::io::{self, BufRead, StdinLock, StdoutLock, Write};
pub struct PromptSet<R, W>
where
R: BufRead,
W: Write,
{
pub reader: R,
pub writer: W,
}
impl<R, W> PromptSet<R, W>
where
R: BufRead,
W: Write,
{
pub fn new(reader: R, writer: W) -> PromptSet<R, W> {
return PromptSet {
reader: reader,
writer: writer,
};
}
pub fn default<'a>() -> PromptSet<StdinLock<'a>, StdoutLock<'a>> {
let stdin = io::stdin();
let stdout = io::stdout();
return PromptSet {
reader: stdin.lock(),
writer: stdout.lock(),
};
}
pub fn prompt(&mut self, question: &str) -> String {
let mut input = String::new();
write!(self.writer, "{}: ", question).unwrap();
self.writer.flush().unwrap();
self.reader.read_line(&mut input).unwrap();
return input.trim().to_string();
}
}
fn main() {}
StdinLock
和 StdoutLock
两者都需要声明一个生命周期。更复杂的是,我认为原来的stdin()
/stdout()
Handlebars 至少要和锁一样长。我想要引用 StdinLock
和 StdoutLock
和我一样长寿PromptSet
确实如此,但无论我尝试什么,我都无法让它工作。这是我不断收到的错误:
error[E0597]: `stdin` does not live long enough
--> src/main.rs:30:21
|
30 | reader: stdin.lock(),
| ^^^^^ borrowed value does not live long enough
...
33 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the method body at 25:5...
--> src/main.rs:25:5
|
25 | / pub fn default<'a>() -> PromptSet<StdinLock<'a>, StdoutLock<'a>> {
26 | | let stdin = io::stdin();
27 | | let stdout = io::stdout();
28 | |
... |
32 | | };
33 | | }
| |_____^
error[E0597]: `stdout` does not live long enough
--> src/main.rs:31:21
|
31 | writer: stdout.lock(),
| ^^^^^^ borrowed value does not live long enough
32 | };
33 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the method body at 25:5...
--> src/main.rs:25:5
|
25 | / pub fn default<'a>() -> PromptSet<StdinLock<'a>, StdoutLock<'a>> {
26 | | let stdin = io::stdin();
27 | | let stdout = io::stdout();
28 | |
... |
32 | | };
33 | | }
| |_____^
我完全有可能不理解生命周期的概念或其他 super 基础的概念。
最佳答案
lock
方法的签名是 fn lock(&self) -> StdinLock
,当使用生命周期注释完全扩展时,它是 fn lock<'a>(&'a self) -> StdinLock<'a>
.因此 StdinLock
只能活到lock
的值方法被调用。由于您定义了 stdin
在这个函数中,StdinLock
不能超过功能。这与 returning a reference to a local value 相同.你也can't return the reference and the referred-to value together .
您不能这样做,也无法解决它。唯一的解决办法是拥有 default
方法采取 Stdin
和一个 Stdout
对象作为参数。
就是说,您可以解决它。是的,我知道,我刚刚说的恰恰相反,但它更像是“除了我以外没有人会使用标准输入/标准输出”(又名,println!
将不再有效!)。
在 Rust 1.26 中,您可以使用 Box::leak
泄漏 Stdin
到 &'static Stdin
,这将产生一个 StdinLock<'static>
.在 Rust 1.26 之前,您可以使用 leak
crate :
pub fn default() -> PromptSet<StdinLock<'static>, StdoutLock<'static>> {
let stdin = Box::leak(Box::new(io::stdin()));
let stdout = Box::leak(Box::new(io::stdout()));
PromptSet {
reader: stdin.lock(),
writer: stdout.lock(),
}
}
关于rust - 有没有一种方法可以在构造函数中使用锁定的标准输入和输出,使其与您正在构造的结构一样长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41549516/