as
を適用可能かどうかわからないからです。 制約からは std::ops::Add
が定義されている独自の型も受け入れる可能性があり、それが as
を使える場面とは限りません。
TryInto
で制約し、 try_into
で変換するのがよいでしょう。
rust
1fn main() {
2 let t = some_operation::<u32>(323);
3 println!("{}", t);
4}
5
6fn some_operation<T>(num: T) -> T
7where
8 T: std::ops::Add<Output = T>,
9 usize: std::convert::TryInto<T>,
10 <usize as std::convert::TryInto<T>>::Error: std::fmt::Debug,
11{
12 let num2: usize = 32;
13 num + num2.try_into().unwrap()
14}
この制約では T
が usize
よりも小さい可能性があり、大きい型から小さい型へと安全に変換できるとは限りません。 (なので Into
が定義されておらず TryInto
を使う必要がある。) この例では 32
という値が固定なので必要な状況に対して安全であることがわかっていますから unwrap
で潰していますけども、状況によっては適切にエラー処理もしてください。
型を性質で制約するのではなく特定の型に限るのであれば独自のトレイトで必要な型にだけ impl
するという手法もあります。 固定値 (定数) もこの段階で型を決めてしまえば関数の中で変換処理を入れる必要もありません。 考慮するのを忘れた予想外の型で使われることがないので場合によってはこういう方法を使った方がよいこともあるでしょう。
rust
1fn main() {
2 let t = some_operation::<u32>(323);
3 println!("{}", t);
4}
5
6trait Operatable: std::ops::Add<Output = Self> + std::marker::Sized {
7 const DATA: Self;
8}
9
10impl Operatable for u32 {
11 const DATA: Self = 32u32;
12}
13
14impl Operatable for u64 {
15 const DATA: Self = 32u64;
16}
17
18fn some_operation<T: Operatable>(num: T) -> T {
19 num + T::DATA
20}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/04/28 13:34
2022/04/28 13:36
2022/04/28 14:37 編集
2022/04/29 03:03 編集
2022/05/04 15:11