Как вы видели, оператор Rust as
очень ограничен в своих действиях. Согласно Rust manual,
Числовое значение может быть присвоено любому цифровому типу. Необработанное значение указателя может быть добавлено к типу целого типа или необработанного указателя. Любые другие роли не поддерживаются и не будут компилироваться.
Кроме того, Rust не делает какое-либо подразумеваемого время выполнения числового принуждения, поэтому вы должны явно принуждать аргументы операторов сравнения к тому же типу (с Ord
определяет lt
метод с прототипом fn lt(&self, other: &Self)
).
Возникает интересный вопрос - к какому типу следует аргументы оператора <
в вашей compare
функции быть литой, T
или int
(предполагаемый тип 42
)? В этом случае вам нужно сравнить n
со значением 42
после преобразования в T
. Самый простой способ выполнить это, оставаясь общим, - потребовать, чтобы T
реализовал признак FromPrimitive
, содержащийся во внешнем num
crate, который предоставляет методы получения значения типа T
из int
(или других примитивных числовых типов ржавчины).Ваша compare
функция может быть записана следующим образом:
extern crate num;
use num::FromPrimitive;
fn compare<T: Ord + FromPrimitive>(n: T) -> bool {
n > FromPrimitive::from_int(42).expect("42 must be convertible to type of n")
}
Чтобы проверить это, я создал простой BinaryNumber
тип, который представляет собой двоичное число как массив bool
:
use std::num::abs;
type Bits = [bool, ..64];
struct BinaryNumber {
priv negbit: bool,
priv bits: Bits,
}
fn bits_from_u64(n: u64) -> Bits {
let mut bits = [false, ..64];
for i in range(0u, 64u) {
if ((1 << i) & n) != 0 {
bits[i] = true;
}
}
bits
}
impl FromPrimitive for BinaryNumber {
fn from_u64(n: u64) -> Option<BinaryNumber> {
Some(BinaryNumber {
negbit: false,
bits: bits_from_u64(n.to_u64().unwrap())
})
}
fn from_i64(n: i64) -> Option<BinaryNumber> {
Some(BinaryNumber {
negbit: n < 0,
bits: bits_from_u64(abs(n).to_u64().unwrap())
})
}
}
impl Eq for BinaryNumber {
fn eq(&self, other: &BinaryNumber) -> bool {
if self.negbit != other.negbit { return false }
for i in range(0, 64).map(|i| 64 - 1 - i) {
if self.bits[i] != other.bits[i] {
return false;
}
}
true
}
}
impl Ord for BinaryNumber {
fn lt(&self, other: &BinaryNumber) -> bool {
match (self.negbit, other.negbit) {
(true, false) => true,
(false, true) => false,
_ => {
let neg = self.negbit;
for i in range(0, 64).map(|i| 64 - 1 - i) {
if neg && self.bits[i] && !other.bits[i] {
return true;
} else if !self.bits[i] && other.bits[i] {
return true;
}
}
false
}
}
}
}
Затем следующий код
fn main() {
let x: BinaryNumber = FromPrimitive::from_int(0).unwrap();
let y: BinaryNumber = FromPrimitive::from_int(42).unwrap();
let z: BinaryNumber = FromPrimitive::from_int(100).unwrap();
println!("compare(x) = {}", compare(x));
println!("compare(y) = {}", compare(y));
println!("compare(z) = {}", compare(z));
}
печатает
compare(x) = false
compare(y) = false
compare(z) = true
Я не эксперт, но я понимаю, что вы не можете сделать 20> 10,5 в ржавчине. Это означает, что вы не можете сравнивать более двух разных типов. – sunny1304
Исправить. Я надеюсь, что есть способ автоматически включить константу в совместимый тип. Константы, вероятно, должны быть нетипизированы, в первую очередь, как в Go. – Gunchars