reverse_kacejot
@reverse_kacejot
Junior C++ Developer, bachelor of Applied Math

Как скастовать шаблонный тип T: Num к любому другому типу, реализующий Num?

Есть crate num.
У него есть trait Num, который описывает свойства всех числовых типов в Rust (как примитивных, так и не очень).

В не шаблонном коде я могу себе позволить скастовать любой числовой тип к любому другому (ответственность за сужение типов я беру на себя). Однако я не могу найти тот же способ для шаблонного кода.
К примеру, есть у меня тип T, который реализует Num. Скорее всего, очевидно, что его можно кастовать к любому другому типу, реализующий Num (во всяком случае, примитивные типы - точно можно).
Но компайлер раста говорит мне, что это нетривиальный каст (в нем задействованы нетривиальные типы - T, даже если это обычный u32, T всё равно нетривиальный, потому как все проверки проводятся до инстанцирования, что бесит, где мои плюсы?) и что нужно юзать либо Into, либо From (к сожалению, это рантайм).

Изначально код был такой, я и ожидал, что он не скомпилится:
pub fn foo<U>(bar: U) -> u8
where
    U: Num,
{
    bar as u8
}

Выхлоп:
error[E0605]: non-primitive cast: `U` as `u8`
  --> src\map\chunk.rs:54:9
   |
54 |         bar as u8
   |         ^^^^^^^^^
   |
   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait


Потом я сделал как просили в ошибке:
pub fn foo<U>(bar: U) -> u8
where
    U: Num + Into<u8>,
{
    bar.into()
}

fn main() {
    let float = 0f32;
    foo(float);
}


Ошибка:
error[E0277]: the trait bound `u8: std::convert::From<f32>` is not satisfied
  --> src\main.rs:45:5
   |
36 | pub fn foo<U>(bar: U) -> u8
   |        ---
37 | where
38 |     U: Num + Into<u8>,
   |              -------- required by this bound in `foo`
...
45 |     foo(float);
   |     ^^^ the trait `std::convert::From<f32>` is not implemented for `u8`
   |
   = help: the following implementations were found:
             <u8 as std::convert::From<bool>>
             <u8 as std::convert::From<std::num::NonZeroU8>>
   = note: required because of the requirements on the impl of `std::convert::Into<u8>` for `f32`


Если кто-то с этим сталкивался, то подскажите, плиз, как вы это решили.
  • Вопрос задан
  • 95 просмотров
Решения вопроса 1
john36allTa
@john36allTa
That`s calling Walker
Странное желание, но вот Вам решение:
extern crate num;

use num::ToPrimitive;

pub fn foo<T>(bar: T) -> Option<u8> where T: ToPrimitive,
{
    bar.to_u8()
}
fn main(){
    println!("That's {}", foo(2.5f32).unwrap())
}
// That's 2
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
08 апр. 2020, в 00:40
15000 руб./за проект
07 апр. 2020, в 23:31
50000 руб./за проект