我想写一个函数tokenize
这需要 char
s 来自迭代器。像这样:
fn tokenize<F: IntoIterator<Item=char>>(file: F)
如果我想使用 &str
有了这个功能,我可以这样做:
tokenize("foo".chars())
可以正常工作。
现在,我想避免 .chars()
专为类型 &str
,因为我知道,如果给我一个 &str
, 我可以通过调用 .chars()
来实现我想要的效果.
我尝试声明一个新特征,IntoChars
, 并为 &str
实现它:
trait IntoChars {
type T: Iterator<Item=char>;
fn into_chars(&self) -> Self::T;
}
impl<'a> IntoChars for &'a str {
type T = Chars<'a>;
fn into_chars(&self) -> Self::T {
self.chars()
}
}
如果那么我的函数是这样的:
tokenize<F: IntoChars>(file: F)
它有效。好的!但我想实现 IntoChars
也适用于可以给我字符的任何类型,即。是IntoIterator<Item=char>
.
impl<T: IntoIterator<Item=char>> IntoChars for T {
type T = T::IntoIter;
fn into_chars(self) -> Self::T {
self.into_iter()
}
}
那是行不通的。有两个原因:
-
IntoIter::into_iter
需要self
,但是IntoChars::into_chars
需要&self
.这是因为我不想消费&str
当调用其into_chars
时不必要的方法。有什么方法可以同时实现这两个目标吗? - 好吧,假设我做了
IntoChars::into_chars
拿个self
.这仍然不起作用;我得到:error: conflicting implementations for trait `IntoChars` [E0119]
.但是如果我删除impl<'a> IntoChars for &'a str
, 我得到error: the trait `core::iter::Iterator` is not implemented for the type `&str`
.为什么会发生冲突?
我有什么办法可以做到这一点?
最佳答案
让我们看看您的两个实现,我以更详细的形式重写了它们:
impl<T> IntoChars for T
where T: IntoIterator<Item = char>
impl<'a> IntoChars for &'a str
当拥有特征 IntoIterator
或类型 &str
的人决定为 &str< 实现
?突然之间,对于相同的特性,您将有冲突的实现; IntoIterator
时,编译器应该做什么&str
的 IntoChars
有两种实现方式。
此问题的其他关键词是特质连贯性和孤儿规则。
为了能够编译它,你需要 impl specialization ,这是一个尚未被接受的 RFC。
关于rust - 采用任何可以产生 char 迭代器的类型,加上 &str,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32672508/