Próbuję zaimplementować szablony ekspresji w stylu C++ w Rust przy użyciu cech i przeciążenia operatora. Utknąłem próbując przeciążać "+" i "*" dla każdej struktury szablonu wyrażenia. Kompilator narzeka implementacji Add
i Mul
cecha:Przeciążanie operatora dla wszystkich struktur z cechą w Rust
error: cannot provide an extension implementation where both trait and type are not defined in this crate
Błąd miałoby sensu, jeśli typ starałem się wdrożyć cechę dla był constructible bez mojej skrzyni, ale typ jest rodzajowy, które muszą wdrożyć HasValue
cecha, którą zdefiniowałem.
Oto kod:
trait HasValue {
fn get_value(&self) -> int;
}
// Val
struct Val {
value: int
}
impl HasValue for Val {
fn get_value(&self) -> int {
self.value
}
}
// Add
struct AddOp<T1: HasValue + Copy, T2: HasValue + Copy> {
lhs: T1,
rhs: T2
}
impl<T1: HasValue + Copy, T2: HasValue + Copy> HasValue for AddOp<T1, T2> {
fn get_value(&self) -> int {
self.lhs.get_value() + self.rhs.get_value()
}
}
impl<T: HasValue + Copy, O: HasValue + Copy> Add<O, AddOp<T, O>> for T {
fn add(&self, other : &O) -> AddOp<T, O> {
AddOp { lhs: *self, rhs: *other }
}
}
// Mul
struct MulOp<T1: HasValue + Copy, T2: HasValue + Copy> {
lhs: T1,
rhs: T2
}
impl<T1: HasValue + Copy, T2: HasValue + Copy> HasValue for MulOp<T1, T2> {
fn get_value(&self) -> int {
self.lhs.get_value() * self.rhs.get_value()
}
}
impl<T: HasValue + Copy, O: HasValue + Copy> Mul<O, MulOp<T, O>> for T {
fn mul(&self, other : &O) -> MulOp<T, O> {
MulOp { lhs: *self, rhs: *other }
}
}
fn main() {
let a = Val { value: 1 };
let b = Val { value: 2 };
let c = Val { value: 2 };
let e = ((a + b) * c).get_value();
print!("{}", e);
}
Myśli?
Innym rozwiązaniem byłoby stworzenie nowej cechy i mieć cechę zaimplementować zarówno "HasValue" i "Copy". Następnie można wprowadzić ogólną implementację 'Dodaj' dla tej cechy. –
@ MatthieuM. Jesteś pewny ? Nie widzę, jak rozwiązuje problem, ponieważ nadal można zaimplementować tę nową cechę dla już istniejącego typu. – Levans
Teoretycznie jest to poprawne, ponieważ podczas implementowania super-cechy dla typu, musisz wiedzieć, czy ten typ implementuje już jakąkolwiek subtrait (i tym samym może zdecydować, czy zignorować domyślną implementację supertytu, czy podnieść błąd). W praktyce nie wiem, czy Rust pozwala na to jeszcze, i jeśli robi to, którą semantykę wybrał (ignorowanie lub błąd). –