Rust: наследование условных признаков

#rust #traits

#Ржавчина #Трейты

Вопрос:

Например, я хочу написать признак для контейнеров в Rust:

 trait Container: Default {
    type ValueType;
}
 

Но также я хочу, чтобы все Container s также могли Clone быть разделены только тогда, когда Container::ValueType могут быть разделены Clone :

 // not Rust code
trait Container: Default   Clone if Self::ValueType: Clone {
    type ValueType;
}
 

Конечно, я мог бы условно реализовать Clone признак для самого конкретного контейнера:

 struct MyVec<T> {}

impl<T: Clone> Clone for MyVec<T> {/**/}
 

или использовать derive(Clone) , но я хочу выразить свое намерение для Container trait , а не для реализации типов.

Ответ №1:

Существует аналогичный синтаксис:

 trait Container: Default   Clone where Self::ValueType: Clone {
                              // ^^^^^
    type ValueType;
}
 

Но это не условно, Container может быть реализовано только для типов, которые соответствуют всем ограничениям: Default , Clone , и Self::ValueType is Clone .


Я не уверен, что это было бы полезно. Ограничения Rust trait являются явными, что означает, что вы не можете использовать что-либо, если нет ограничения. Так что вам все равно придется включить их в ограничения.

 fn use_container<C: Container>(c: C)
where
    C: Clone,
    C::ValueType: Clone
{
  let _ = c.clone();
  let _ = c.get_element().clone();
}
 

И вы должны реализовать Clone на конкретных типах независимо.

Если ваша цель состоит в том, чтобы просто указать, что «для реализаций Container , если элементы Clone , то контейнер должен быть клонирован», преобладающий шаблон в идиоматическом Rust заключается в том, чтобы ограничивать только то, что вам нужно, когда вам это нужно. (т. Е. Если функции необходимо клонировать контейнер, ограничивать on C: Clone ; если функция тольконеобходимо клонировать элемент, ограничить C::ValueType: Clone ).

Комментарии:

1. Я никогда where Self::ValueType: Clone раньше не видел синтаксиса. Является ли значение таким же, как при указании ограничения на ValueType само использование type ValueType: Clone ?

2. @user4815162342 В этом случае они были бы одинаковыми, и я бы предпочел последнее. where Синтаксис доступен, поскольку он может применяться к большему количеству вещей. Например: trait Container: Iterator where Self::Item: Clone .

3. О, верно, это имеет смысл, и я видел это в этом варианте. В более сложных признаках это часто определяется как where <Self as Iterator>::Item: Clone .