当我研究 Rust 时,我试图编写一个 Rust 函数来查看任何可迭代的字符串。
我最初的尝试是
fn example_1(iter: impl Iterator<Item=&str>);
fn example_2(iter: impl Iterator<Item=&String>);
// ...
这需要针对不同情况的两个函数。
我也试过把上面的案例合二为一,结果是:
fn example_3<'a, T: 'a + ?Sized + Deref<str>>(iter: impl Iterator<Item=&'a T>);
可以同时接受 Iterator<Item=&String>
和 Iterator<Item=&str>
, 但不是 Iterator<String>
(因为最后一个需要在函数体中再借用一次)。此外,它看起来比实际情况要复杂得多。
我当然可以使用自定义 trait
来实现它,可能涉及 AsRef
,但我认为我可能缺少更好更清晰的方法。
最佳答案
这是 std::borrow::Borrow
的绝佳用例. Borrow
适用于可以合理地借用为外观相似但字面上不同的类型的类型( String
借用为 &str
, PathBuf
借用为 &Path
等)
fn example<'a, I, T>(iter: I)
where I : Iterator<Item=T>,
T : Borrow<str> {
for x in iter {
let my_string: &str = x.borrow();
// ...
}
}
请注意,这适用于 String
和 &str
,但不是,正如您在示例中所建议的那样,&String
.如果你最终得到一个 &String
的迭代器, 然后你可能会质疑你是如何到达那里的( &String
和 &Vec<T>
一样没用;客观上它在各方面都比 &str
差)。但是如果你出于某种原因结束了一个 &String
的迭代器, 你可以到 &str
与
my_iter.map(|x| &**x));
一个*
摆脱 &
, 一个 *
取消引用 String
至 str
, 然后是 &
借用str
.恭喜!你是一个two-star programmer现在。
或者,更简单(感谢 user4815162342),
my_iter.map(|x| x.as_str())
关于string - 类似 str 的迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69153440/