英文:
How can you implement a std Trait for every type that already implements other related std traits
问题
我现在有几个结构体,我已经在它们上面实现了Add和Neg特质。现在我想在它们上面实现Sub特质。我想要的是能够编写类似以下的代码:
impl<T: Add + Neg> Sub for T {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self + (-rhs)
}
}
但这给我报错:
只有在至少有一个实现它的类型是本地的情况下,才能实现外部特质
只有在当前 crate 中定义的特质才能为类型参数实现
上次我遇到这个问题时,我复制粘贴了每个相关类型的impl块。虽然不是很耗时,但很丑陋。只找到了这个StackOverflow问题 ,从2015年开始,显然唯一的方法是使用宏,但在我的情况下会更糟。我想知道现在是否有其他方法可以实现这个。
英文:
So I have several structs I have implemented the Add and Neg traits on.
I now want to implement the Sub trait on them
What I want is to be able to write something along those lines
impl<T: Add + Neg> Sub for T{
type Output = self
fn sub(self, rhs:Self) -> Self{
self + (-rhs)
}
}
but this gives me the error:
implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
only traits defined in the current crate can be implemented for a type parameter
last time I encountered the problem I had copy paste the impl block for every relevant type. not that time consuming but ugly.
only found this stackoverflow question from 2015, apparently the only way to do this was with macros but in my case it would be worse. I'm wondering if there's another way to do that now
答案1
得分: 0
不能。
Rust 使用孤儿规则(Orphan Rule)来确保特质实现的一致性。
一致性意味着特定类型只应该为某个特质实现零次或一次(当某些类型为同一特质实现了多次时,称为“重叠”),这可以在单次编译中轻松检查。但实际上,在不同的 crate 中定义类型、特质和实现时,仍然可以发生重叠。
crate 系统被设计成一个断言,即在引入新 crate 到编译中时,它必须是纯粹的附加内容(这意味着它不能破坏任何现有的代码)。换句话说,只要每个依赖项可以单独编译而不会出现问题,就应该确保一个 crate 及其所有依赖项都可以编译无误。一个非常明显的例子是,当 crate a
和 b
是不相关的 crate,它们都为某个特定特质提供了自己的类型实现时,它们可以单独成功编译,但如果另一个特质 c
依赖于 a
和 b
,那么对于 crate c
来说,这种类型的特质实现是重叠的。
孤儿规则可以简单解释为,对于特定类型和特质,只有类型的定义 crate 或特质的定义者才能为该类型定义特质的实现。换句话说,一旦定义了类型和特质,类型如何实现该特质完全由定义者决定,不再可以由下游 crate 添加或重叠。因此,对于任何能够看到类型和特质的 crate,它们必须看到相同的零次或一次类型的特质实现。
请注意,泛型参数也可能引用外部类型(即当前 crate 未定义的类型),不可能为泛型参数实现外部特质。
英文:
No, you can't.
Rust uses the Orphan Rule to ensure the coherence of the trait implementations.
Coherence means that a certain type should only implement a trait for zero or one time (It is called 'overlapping' when some type implements a trait for more than once), which could be easily checked during a single compilation. But in fact, implementations could still overlap when the types, traits, and implementations are defined across crates.
The crate system is designed with an assertion of that it must be purely additional (which mean it cannot break any existing code) when any new crate is introduced to a compilation. In other words, it should be ensured that A crate, along with all of its dependencies, could compile with no problem, as long as each dependencies could compile alone with no problem. A very obvious example is that, when crate a
and b
are irrelative crates that both provide their implementation of a certain type for a certain trait, they could successfully compile alone, but if another trait c
depends on both a
and b
, that implementation of such type for such trait, as crate c
could see, is overlapping.
The Orphan Rule could be simply explained as that, as for a certain type and a certain trait, only the definer crate of the type, or the definer of the trait, could define implementation of the trait for the type. In other words, once both the type and the trait are defined, whether and how the type implements the trait is fully decided and can no longer be added or overlapped by the down-stream crates. Therefore, as for any crates that could see both the type and the trait, they must see the same zero or one implementation of a trait for a type.
Note that a generic parameter may also refer to a foreign type (a type that is not defined by the current crate), it is not possible to implement a foreign trait for a generic parameter
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论