#generics #rust
Вопрос:
Учитывая Base<Foo>
и Base<Bar>
, есть ли способ реализовать Add
так, чтобы только Base<Foo> Base<Bar>
и Base<Bar> Base<Foo>
компилировать? т.е.. добавлять только, если конкретные типы разные?
В моем случае они могут быть только 2 разных типов.
Пример:
Учитывая
#[derive(Debug)]
struct Base<T> {
n: u32,
_marker: std::marker::PhantomData<T>,
}
trait FooTrait {}
struct FooImpl;
impl FooTrait for FooImpl {}
trait BarTrait {}
struct BarImpl;
impl BarTrait for BarImpl {}
есть ли способ реализовать Add
так, чтобы
let foo: Base<Foo> = Base::new();
let foo2 = foo.clone();
let bar: Base<Bar> = Base::new();
let bar2: bar.clone();
let foobar = foo bar;
let foobar = bar2 foo2;
компилируется, но
let foo: Base<Foo> = Base::new();
let foo2 = foo.clone();
let bar: Base<Bar> = Base::new();
let bar2: bar.clone();
let foofoo = foo foo2;
let barbar = bar bar2;
не так ли?
Я пытался
impl<A, B> Add<Base<B>> for Base<A>
where
A: DerivedATrait,
B: DerivedBTrait,
{
type Output = Base<A>;
fn add(self, rhs: Base<B>) -> Base<A> {
Base::new(self.n rhs.n)
}
}
но это только позволяет Base<A> Base<B>
, а не наоборот, и дополнительная Add
реализация, меняющая границы, не компилируется.
Комментарии:
1. я не уверен, что понимаю, чего вы хотите. вам нужна игровая площадка ?
2. Если вы используете nightly, вы можете попробовать изучить функции
auto_traits
иnegative_impls
. Это должно позволить вам более точно контролировать, какие impls существуют, но я не уверен, применимы ли они к вашей конкретной проблеме.3. @VaillantEtienne, я хочу
Base<Foo> Base<Barr>
иBase<Bar> Base<Foo>
компилировать, ноBase<Foo> Base<Foo>
иBase<Bar> Base<Bar>
не компилировать.4. Вам нужны общие типы? Или вы можете просто
impl Add<Base<Foo>> for Base<Bar>
иimpl Add<Base<Bar>> for Base<Foo>
?