Границы признаков ржавчины для целых типов

#rust #traits #bounds

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

Вопрос:

Предположим, у меня есть свой собственный тип в виде структуры кортежа

 struct MyType(u8);
  

И хотел бы реализовать From признак для других целых типов в общем виде, например

 impl From<T> for MyType {
    fn from(num: T) -> Self {
        MyType((num amp; 0xff) as u8)
    }
}
  

Rust не допускает этого, поскольку у универсальных типов T нет as оператора. Как я могу ограничить T целые типы, чтобы as их можно было использовать? что-то вроде

 impl From<T: Integral> for MyType {...}
  

Ответ №1:

Вы можете использовать num-traits ящик.

PrimInt является соответствующей чертой, которая расширяет NumCast , что позволяет выполнять преобразование между примитивными числовыми типами.

РЕДАКТИРОВАТЬ: вот пример реализации. Это немного некрасиво, потому что многие из соответствующих преобразований возвращаются Option , поскольку они не знают заранее, что значения находятся в диапазоне.

 impl<T: PrimInt> From<T> for MyType {
    fn from(num: T) -> Self {
        let clamped = num amp; T::from(0xFFu8).unwrap();
        Self(clamped.to_u8().unwrap())
    }
}
  

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

1. Вы также можете захотеть конкретно сослаться на приведенный ими пример; где все целые числа реализуются From<u8> и, следовательно 0xFF , могут быть преобразованы в них.

2. Мне не совсем нравится T::from , что возвращает an Option . В стандарте std::convert::From указано, что «Примечание: эта черта не должна завершаться ошибкой. Если преобразование может завершиться неудачей, используйте TryFrom.». Это, похоже, противоречит этой идее. Но спасибо, что указали на num-черты.

3. @Miguel Этот from() метод не из From признака, скорее это метод NumCast с тем же именем. К сожалению, это from::<u8> возвращает параметр, но это имеет смысл для таких вещей, как преобразование u64 в u32 .

4. internals.rust-lang.org/t/… я думаю, это был бы шаг в правильном направлении, с IntToInt чертой и wrapping_to()