Контейнеры, которые поддерживают объекты признаков, являются контейнерами, для которых ?Sized
привязан к их типу содержимого.
По умолчанию при использовании дженериков все типы неявно Sized
, так как это то, что вы хотите большую часть времени, и добавление Sized
почти для каждого дженерика будет раздражать. Это поведение отличается от других черт и его можно избежать, добавив границу ?Sized
.
struct Foo<T>; // implicit `T: Sized` bound. T cannot be a trait object.
struct Bat<T: ?Sized>; // T can be a trait object.
Вы можете увидеть в хранилище , что Rc
действительно раньше был объявлен pub struct Rc<T>
и позже был изменен на pub struct Rc<T: ?Sized>
. GitHub перечисляет это изменение как часть Rust 1.1, но я думаю, нам пришлось подождать 1.2, чтобы получить его в стабильном состоянии.
Другими контейнерами, работающими с объектами-чертами, являются Box
, Arc
, Cell
и другие подобные умным указателям.
Контейнеры, которые не работают с объектами признаков, это Vec
, HashMap
и, как правило, контейнеры, которые могут хранить более одного экземпляра (коллекции). Это связано с тем, что 2 экземпляра одного и того же объекта признаков могут иметь разные размеры (если они имеют разный конкретный тип), а коллекции обычно хранят элементы непрерывно, требуя постоянного размера.