为什么我的 Trait 实现不匹配?
Why does my Trait implementation not match?
如何编译这段代码?
trait Pair<'a, A, B> {
fn first_ref(&'a self) -> &'a A;
fn second_ref(&'a self) -> &'a B;
};
struct PairOwned<A, B> {
first: A,
second: B,
}
// Only implemented for the cases we are interested in ...
impl<'a, A, B> Pair<'a, A, B> for &'a PairOwned<&'a A,&'a B> {
fn first_ref(&'a self) -> &'a A {
self.first
}
fn second_ref(&'a self) -> &'a B {
self.second
}
}
impl<'a, A, B> Pair<'a, A, B> for &'a(&'a A, &'a B) {
fn first_ref(&'a self) -> &'a A {
self.0
}
fn second_ref(&'a self) -> &'a B {
self.1
}
}
fn pair_transformer<'a, I, T>(pairs: I) -> String
where T: Pair<'a, &'a Str, &'a Str> + 'a,
I: Iterator<Item=T> {
let mut s = String::new();
for pair in pairs {
s = s
+ pair.first_ref().as_slice()
+ pair.second_ref().as_slice();
}
s
}
pair_transformer([PairOwned { first: "a", second: "b" }].iter());
pair_transformer([("a", "b")].iter());
编译器说:
tests/lang.rs:902:5: 902:21 error: the trait `pair_trait_for_iteration::Pair<'_, &core::str::Str, &core::str::Str>` is not implemented for the type `&pair_trait_for_iteration::PairOwned<&str, &str>` [E0277]
tests/lang.rs:902 pair_transformer([PairOwned { first: "a", second: "b" }].iter());
^~~~~~~~~~~~~~~~
tests/lang.rs:903:5: 903:21 error: the trait `pair_trait_for_iteration::Pair<'_, &core::str::Str, &core::str::Str>` is not implemented for the type `&(&str, &str)` [E0277]
tests/lang.rs:903 pair_transformer([("a", "b")].iter());
备注
我觉得它与指定应实现特征的各种方式有某种关系,我还没有完全理解这一点。
// As stated in the answer at
//
impl Add<YourType> for YourType { ... }
impl<'r> Add<YourType> for &'r YourType { ... }
impl<'a> Add<&'a YourType> for YourType { ... }
impl<'r, 'a> Add<&'a YourType> for &'r YourType { ... }
使用rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
您的代码中有几个错误:
- 您可能想直接为您的类型实现您的特征,因为特征定义的方法采用特征 by reference([=11 不是这种情况=] 你链接的另一个 post 的特征)
- 您对
OwnedPair { first: "a", second: "b"}
的使用实际上并未被拥有:您的类型将是 OwnedPair<&'static str, &'static str>
所以我包含了带有 String
的示例(它们是被拥有的),因为我假设这就是您所拥有的通缉
- 迭代器返回的项实际上是引用,因此您可能希望将 I 绑定到
Iterator<Item=&'a T>
因为我试图尽可能通用(并且为了使用 OwnedPair<&str,&str>
和 OwnedPair<String,String>
进行编译的示例),我使用了特征 std::borrow::Borrow,这基本上意味着它可以从实现此特征的类型借用对类型 T 的引用。
我还需要使用 ?Sized
作为大多数类型参数的边界。这允许使用在编译时大小未知的类型,并将在 "fat pointer" 后面使用。更多信息在this blog post(有点旧)
这是更正后的完整代码(可在 playpen 中运行)
use std::borrow::Borrow;
trait Pair<'a, A: ?Sized, B: ?Sized> {
fn first_ref(&'a self) -> &'a A;
fn second_ref(&'a self) -> &'a B;
}
struct PairOwned<A, B> {
first: A,
second: B,
}
// Only implemented for the cases we are interested in ...
impl<'a, ARef: ?Sized, BRef: ?Sized, A: Borrow<ARef>, B: Borrow<BRef>> Pair<'a, ARef, BRef> for PairOwned<A,B> {
fn first_ref(&'a self) -> &'a ARef {
self.first.borrow()
}
fn second_ref(&'a self) -> &'a BRef {
self.second.borrow()
}
}
// It should also be possible to be more generic here with Borrow
// But I wanted to leave your original implementation
impl<'a, A: ?Sized, B: ?Sized> Pair<'a, A, B> for (&'a A, &'a B) {
fn first_ref(&'a self) -> &'a A {
self.0
}
fn second_ref(&'a self) -> &'a B {
self.1
}
}
fn pair_transformer<'a, I, T>(pairs: I) -> String
where T: Pair<'a, str, str> + 'a,
I: Iterator<Item=&'a T> {
let mut s = String::new();
for pair in pairs {
s = s
+ pair.first_ref().as_slice()
+ pair.second_ref().as_slice();
}
s
}
fn main() {
pair_transformer([PairOwned { first: "a".to_string(), second: "b".to_string() }].iter());
pair_transformer([PairOwned { first: "a".to_string(), second: "b" }].iter()); // It is even possible to mix String and &str
pair_transformer([PairOwned { first: "a", second: "b" }].iter());
pair_transformer([("a", "b")].iter());
}
如何编译这段代码?
trait Pair<'a, A, B> {
fn first_ref(&'a self) -> &'a A;
fn second_ref(&'a self) -> &'a B;
};
struct PairOwned<A, B> {
first: A,
second: B,
}
// Only implemented for the cases we are interested in ...
impl<'a, A, B> Pair<'a, A, B> for &'a PairOwned<&'a A,&'a B> {
fn first_ref(&'a self) -> &'a A {
self.first
}
fn second_ref(&'a self) -> &'a B {
self.second
}
}
impl<'a, A, B> Pair<'a, A, B> for &'a(&'a A, &'a B) {
fn first_ref(&'a self) -> &'a A {
self.0
}
fn second_ref(&'a self) -> &'a B {
self.1
}
}
fn pair_transformer<'a, I, T>(pairs: I) -> String
where T: Pair<'a, &'a Str, &'a Str> + 'a,
I: Iterator<Item=T> {
let mut s = String::new();
for pair in pairs {
s = s
+ pair.first_ref().as_slice()
+ pair.second_ref().as_slice();
}
s
}
pair_transformer([PairOwned { first: "a", second: "b" }].iter());
pair_transformer([("a", "b")].iter());
编译器说:
tests/lang.rs:902:5: 902:21 error: the trait `pair_trait_for_iteration::Pair<'_, &core::str::Str, &core::str::Str>` is not implemented for the type `&pair_trait_for_iteration::PairOwned<&str, &str>` [E0277]
tests/lang.rs:902 pair_transformer([PairOwned { first: "a", second: "b" }].iter());
^~~~~~~~~~~~~~~~
tests/lang.rs:903:5: 903:21 error: the trait `pair_trait_for_iteration::Pair<'_, &core::str::Str, &core::str::Str>` is not implemented for the type `&(&str, &str)` [E0277]
tests/lang.rs:903 pair_transformer([("a", "b")].iter());
备注
我觉得它与指定应实现特征的各种方式有某种关系,我还没有完全理解这一点。
// As stated in the answer at
//
impl Add<YourType> for YourType { ... }
impl<'r> Add<YourType> for &'r YourType { ... }
impl<'a> Add<&'a YourType> for YourType { ... }
impl<'r, 'a> Add<&'a YourType> for &'r YourType { ... }
使用rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
您的代码中有几个错误:
- 您可能想直接为您的类型实现您的特征,因为特征定义的方法采用特征 by reference([=11 不是这种情况=] 你链接的另一个 post 的特征)
- 您对
OwnedPair { first: "a", second: "b"}
的使用实际上并未被拥有:您的类型将是OwnedPair<&'static str, &'static str>
所以我包含了带有String
的示例(它们是被拥有的),因为我假设这就是您所拥有的通缉 - 迭代器返回的项实际上是引用,因此您可能希望将 I 绑定到
Iterator<Item=&'a T>
因为我试图尽可能通用(并且为了使用 OwnedPair<&str,&str>
和 OwnedPair<String,String>
进行编译的示例),我使用了特征 std::borrow::Borrow,这基本上意味着它可以从实现此特征的类型借用对类型 T 的引用。
我还需要使用 ?Sized
作为大多数类型参数的边界。这允许使用在编译时大小未知的类型,并将在 "fat pointer" 后面使用。更多信息在this blog post(有点旧)
这是更正后的完整代码(可在 playpen 中运行)
use std::borrow::Borrow;
trait Pair<'a, A: ?Sized, B: ?Sized> {
fn first_ref(&'a self) -> &'a A;
fn second_ref(&'a self) -> &'a B;
}
struct PairOwned<A, B> {
first: A,
second: B,
}
// Only implemented for the cases we are interested in ...
impl<'a, ARef: ?Sized, BRef: ?Sized, A: Borrow<ARef>, B: Borrow<BRef>> Pair<'a, ARef, BRef> for PairOwned<A,B> {
fn first_ref(&'a self) -> &'a ARef {
self.first.borrow()
}
fn second_ref(&'a self) -> &'a BRef {
self.second.borrow()
}
}
// It should also be possible to be more generic here with Borrow
// But I wanted to leave your original implementation
impl<'a, A: ?Sized, B: ?Sized> Pair<'a, A, B> for (&'a A, &'a B) {
fn first_ref(&'a self) -> &'a A {
self.0
}
fn second_ref(&'a self) -> &'a B {
self.1
}
}
fn pair_transformer<'a, I, T>(pairs: I) -> String
where T: Pair<'a, str, str> + 'a,
I: Iterator<Item=&'a T> {
let mut s = String::new();
for pair in pairs {
s = s
+ pair.first_ref().as_slice()
+ pair.second_ref().as_slice();
}
s
}
fn main() {
pair_transformer([PairOwned { first: "a".to_string(), second: "b".to_string() }].iter());
pair_transformer([PairOwned { first: "a".to_string(), second: "b" }].iter()); // It is even possible to mix String and &str
pair_transformer([PairOwned { first: "a", second: "b" }].iter());
pair_transformer([("a", "b")].iter());
}