为具有 From 类型的结构实现 PartialEq
Implementing PartialEq for a struct with From types
我正在尝试在我创建的结构和我的结构实现 From
特性的其他类型之间实现 PartialEq
。实际代码更复杂,并为其他类型实现 From
,但这是核心问题的简化版本。
我希望能够做到:
let s = Data::from(5);
assert_eq!(5, s);
这是基本代码:
struct Data {
data: i64,
}
impl From<i64> for Data {
fn from(v: i64) -> Data {
Data { data: v }
}
}
impl<'a> From<&'a i64> for Data {
fn from(v: &'a i64) -> Data {
Data { data: v.clone() }
}
}
这是我的第一次尝试:
impl<T> PartialEq<T> for Data
where T: Into<Data>
{
fn eq(&self, other: &T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
但我得到一个错误:
error: the trait bound `Data: std::convert::From<&T>` is not satisfied [--explain E0277]
--> <anon>:21:17
|>
21 |> let o = Data::from(other);
|> ^^^^^^^^^^
help: consider adding a `where Data: std::convert::From<&T>` bound
note: required by `std::convert::From::from`
所以我将特征绑定更改为编译器建议的内容,并添加了所有请求的生命周期以修复 missing lifetime specifier
错误:
impl<'a, T> PartialEq<T> for Data
where T: 'a, Data: From<&'a T>
{
fn eq(&self, other: &'a T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
我从中得到
error: method not compatible with trait [--explain E0308]
--> <anon>:31:5
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^ lifetime mismatch
note: expected type `fn(&Data, &T) -> bool`
note: found type `fn(&Data, &'a T) -> bool`
note: the anonymous lifetime #2 defined on the block at 31:39...
--> <anon>:31:40
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^
note: ...does not necessarily outlive the lifetime 'a as defined on the block at 31:39
--> <anon>:31:40
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^
help: consider using an explicit lifetime parameter as shown: fn eq(&self, other: &'a T) -> bool
--> <anon>:31:5
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^
现在我迷路了,因为它建议完全按照我所做的去做,但它拒绝了……:/
你只需要一个小小的修改就可以使 PartialEq
工作:需要 Data: From<&'a T>
因为你使用的是 Data::from(other)
而不是 other.into()
:
impl<T> PartialEq<T> for Data
where for<'a> Data: From<&'a T>
{
fn eq(&self, other: &T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
您还需要进行两个微小的修改才能使 assert_eq!
正常工作:
由于您正在为数据实现 PartialEq,RHS 是 T
,LHS 是 Data
,因此您只能使用 Data::from(5) == 5
进行比较,而不是5 == Data::from(5)
.
如果要使用assert_eq!
,则需要实现Debug
。
最终工作代码:
#[derive(Debug)]
struct Data {
data: i64,
}
impl From<i64> for Data {
fn from(v: i64) -> Data {
Data { data: v }
}
}
impl<'a> From<&'a i64> for Data {
fn from(v: &'a i64) -> Data {
Data { data: v.clone() }
}
}
impl<T> PartialEq<T> for Data
where for<'a> Data: From<&'a T>
{
fn eq(&self, other: &T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
fn main() {
let s = Data::from(5);
assert_eq!(s, 5);
}
编译器是正确的:添加 where Data: From<&T>
是 正确的做法。但是正如您已经注意到的,在这种情况下需要一个生命周期说明符。但是我们如何声明它?
我们想对编译器说的话:
Data
should implement From<&'a T>
for any lifetime 'a
我们不能在impl
块上声明生命周期,因为这表达了不同的东西。我们需要使用 “higher-ranked lifetime bounds”,如下所示:
where Data: for<'a> From<&'a T>
// ^^^^^^^
这解决了您的主要问题。
还有两个无关紧要的附加问题:
- 您需要交换
assert_eq!()
中的参数,因为 PartialEq
的使用方式:assert_eq!(s, 5)
- 你需要
#[derive(Debug)]
你的 Data
类型
您可以找到 工作版本 here on the playground。
我正在尝试在我创建的结构和我的结构实现 From
特性的其他类型之间实现 PartialEq
。实际代码更复杂,并为其他类型实现 From
,但这是核心问题的简化版本。
我希望能够做到:
let s = Data::from(5);
assert_eq!(5, s);
这是基本代码:
struct Data {
data: i64,
}
impl From<i64> for Data {
fn from(v: i64) -> Data {
Data { data: v }
}
}
impl<'a> From<&'a i64> for Data {
fn from(v: &'a i64) -> Data {
Data { data: v.clone() }
}
}
这是我的第一次尝试:
impl<T> PartialEq<T> for Data
where T: Into<Data>
{
fn eq(&self, other: &T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
但我得到一个错误:
error: the trait bound `Data: std::convert::From<&T>` is not satisfied [--explain E0277]
--> <anon>:21:17
|>
21 |> let o = Data::from(other);
|> ^^^^^^^^^^
help: consider adding a `where Data: std::convert::From<&T>` bound
note: required by `std::convert::From::from`
所以我将特征绑定更改为编译器建议的内容,并添加了所有请求的生命周期以修复 missing lifetime specifier
错误:
impl<'a, T> PartialEq<T> for Data
where T: 'a, Data: From<&'a T>
{
fn eq(&self, other: &'a T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
我从中得到
error: method not compatible with trait [--explain E0308]
--> <anon>:31:5
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^ lifetime mismatch
note: expected type `fn(&Data, &T) -> bool`
note: found type `fn(&Data, &'a T) -> bool`
note: the anonymous lifetime #2 defined on the block at 31:39...
--> <anon>:31:40
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^
note: ...does not necessarily outlive the lifetime 'a as defined on the block at 31:39
--> <anon>:31:40
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^
help: consider using an explicit lifetime parameter as shown: fn eq(&self, other: &'a T) -> bool
--> <anon>:31:5
|>
31 |> fn eq(&self, other: &'a T) -> bool {
|> ^
现在我迷路了,因为它建议完全按照我所做的去做,但它拒绝了……:/
你只需要一个小小的修改就可以使 PartialEq
工作:需要 Data: From<&'a T>
因为你使用的是 Data::from(other)
而不是 other.into()
:
impl<T> PartialEq<T> for Data
where for<'a> Data: From<&'a T>
{
fn eq(&self, other: &T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
您还需要进行两个微小的修改才能使 assert_eq!
正常工作:
由于您正在为数据实现 PartialEq,RHS 是
T
,LHS 是Data
,因此您只能使用Data::from(5) == 5
进行比较,而不是5 == Data::from(5)
.如果要使用
assert_eq!
,则需要实现Debug
。
最终工作代码:
#[derive(Debug)]
struct Data {
data: i64,
}
impl From<i64> for Data {
fn from(v: i64) -> Data {
Data { data: v }
}
}
impl<'a> From<&'a i64> for Data {
fn from(v: &'a i64) -> Data {
Data { data: v.clone() }
}
}
impl<T> PartialEq<T> for Data
where for<'a> Data: From<&'a T>
{
fn eq(&self, other: &T) -> bool {
let o = Data::from(other);
self.data == o.data
}
}
fn main() {
let s = Data::from(5);
assert_eq!(s, 5);
}
编译器是正确的:添加 where Data: From<&T>
是 正确的做法。但是正如您已经注意到的,在这种情况下需要一个生命周期说明符。但是我们如何声明它?
我们想对编译器说的话:
Data
should implementFrom<&'a T>
for any lifetime'a
我们不能在impl
块上声明生命周期,因为这表达了不同的东西。我们需要使用 “higher-ranked lifetime bounds”,如下所示:
where Data: for<'a> From<&'a T>
// ^^^^^^^
这解决了您的主要问题。
还有两个无关紧要的附加问题:
- 您需要交换
assert_eq!()
中的参数,因为PartialEq
的使用方式:assert_eq!(s, 5)
- 你需要
#[derive(Debug)]
你的Data
类型
您可以找到 工作版本 here on the playground。