Reputation: 407
For example, I want to write the trait for containers in Rust:
trait Container: Default {
type ValueType;
}
But also I want that all Container
s also can be Clone
d only when Container::ValueType
can be Clone
d:
// not Rust code
trait Container: Default + Clone if Self::ValueType: Clone {
type ValueType;
}
Of course, I could conditionally implement Clone
trait for the concrete container itself:
struct MyVec<T> {}
impl<T: Clone> Clone for MyVec<T> {/**/}
or use derive(Clone)
, but I want to express my intention for Container
trait, not for implementing types.
Upvotes: 4
Views: 1156
Reputation: 60152
This similar syntax exists:
trait Container: Default + Clone where Self::ValueType: Clone {
// ^^^^^
type ValueType;
}
But it isn't conditional, Container
can only be implemented for types that statisfy all constraints: Default
, Clone
, and Self::ValueType
is Clone
.
I'm not sure this would be useful. Rust trait constraints are explicit, meaning you can't use something unless the constraint is there. So you'd have to include them in the constraints anyway.
fn use_container<C: Container>(c: C)
where
C: Clone,
C::ValueType: Clone
{
let _ = c.clone();
let _ = c.get_element().clone();
}
And you have to implement Clone
on the concrete types regardless.
If your goal is just to indicate that "for implementations of Container
if the elements are Clone
then the container should be clone", the prevailing pattern in idiomatic Rust is to only constrain what you need when you need it. (i.e. if a function needs to clone the container, constrain on C: Clone
; if a function only needs to clone an element, constrain on C::ValueType: Clone
).
Upvotes: 8