やりたいこと
UnsigedなやつとSignedなやつで関数のふるまいを変えたい
ソースコード
rust
1 2use std::{ops::Mul, process::Output}; 3use num::{Signed, Unsigned}; 4 5struct Sample<T>(T); 6// Unsigedなprimitive型に対する計算(負の場合を考慮しない) 7impl<T> Mul<u32> for Sample<T> { 8 type Output = Self; 9 fn mul(self, rhs: u32) -> Self::Output { 10 todo!() 11 } 12} 13// Signedなprimitive型に対する計算(負の場合も実装する) 14impl<S:Signed + 'static + Copy,T> Mul<S> for Sample<T> { 15 type Output = Self; 16 fn mul(self, rhs: S) -> Self::Output { 17 todo!() 18 } 19}
エラー
conflicting implementations of trait `std::ops::Mul<u32>` for type `Sample<_>` upstream crates may add a new impl of trait `num::Signed` for type `u32` in future versions
こんにちは。いまある情報だけですと、エラーの原因も解決方法もわかりません。
質問に以下の情報を追記していただけないでしょうか?
- エラーメッセージ
- Negトレイトの定義
- 何かクレートを使用しているなら、その情報。(AsPrimitive, WrappingMul, Unsignedトレイトはnum-traitsクレートのものを使っているのですか?)
- もしAsPrimitive, WrappingMul, Unsignedトレイトは自分で定義したものなら、それらの定義
コメントありがとうございます。
すべてのtraitはnum-traitsクレートのものを使ってます。
Unsigedはi32は実装することはなく、u32はSignedを実装することがないことが人間にはわかりますが、コンパイラはわからないので、型境界にUnsignedをつけた型TについてのMul<T>の実装と、i32についてのMul<i32>の実装がコンフリクトするんです。
これをうまくコンフリクトさせずに分けて実装できる、択一型(e.g. Unsignedを実装したらSignedは実装できないし、逆も成り立つ)みたいな型境界はないんですかね。ないとしたら符号付き整数型と符号なし整数型で実装を分けるにはすべての型について実装するしかないですかね。
まずは、tatsuya6502さんの質問にちゃんと応えましょう(念の為、回答者が偉いから従えとかいうことではなく、至極妥当な確認事項だからです).
あと、u32にstd::ops::Negは実装されていないので、その2つの実装がコンフリクトするとは思えません.できれば、ソースコードもあまり省略せずに貼ってほしいです.塩梅が難しいかもしれませんが、不足しているよりは過剰な方が回答しやすいです.
上のソースコードは変更してしまって手元になくなってしまいました。ごめんなさい。
ご指摘にのようにu32はNegを現状実装していませんが、コンパイラはu32がいつかNegを実装するかもしれないから潜在的にconflictしてるよと怒ってきます。これに対処する方法をご存じないですか?
tsutuya6502さんのご指摘のようにSignedなものとUnsigedなものの区別は型境界ではできなさそうなので、実装単位を分けることで対処しようかなと思います。
潜在的なconflictという概念があるんですね.それは知らなかったので、勉強になりました.
unstableな機能としては、negative implsというのがありますが、unstableなので、nightlyでないとコンパイルできなくなりますし、あまりおすすめはしません.
https://doc.rust-lang.org/beta/unstable-book/language-features/negative-impls.html
回答1件
あなたの回答
tips
プレビュー