如何转换我知道是整数的泛型类型?

时间:2014-09-25 15:43:34

标签: casting rust parametric-polymorphism

我想以通用方式检查C API的返回码,结果必须是免费的C类型,例如libc::c_int。有没有办法编写像

这样的函数
fn check<S: PartialOrd + std::num::Zero, T> (x: S) -> Option<T> {
    if std::num::zero::<S>() <= x { Some(x as T) }
    else { None }
}

当我确定STcheck()所有用法的完整类型时?编译器拒绝我的代码抱怨error: non-scalar cast: `S` as `T`

1 个答案:

答案 0 :(得分:5)

针对Rust 1.x进行了更新

将任意类型转换为任意类型是不可能的,而且这几乎是(几乎)你正在尝试做的事情。您需要在类型约束和转换操作中更具体。

extern crate num;

use num::{Zero, NumCast};

fn check<S: PartialOrd+Zero+NumCast, T: NumCast>(x: S) -> Option<T> {
    if x >= S::zero() { Some(num::cast(x).unwrap()) }
    else { None }
}

fn main() {
    let x: i8 = 10;
    let y: Option<i32> = check(x);
    println!("{:?}", y);

    let x: i8 = -10;
    let y: Option<i32> = check(x);
    println!("{:?}", y);
}

我在这里使用来自num crate的特殊特征num::traits::NumCast,它是为所有原始类型实现的,并提供了一个静态方法,可以从实现{{{1}的任何内容转换为这些类型3}}。 num crate还提供了一个函数num::ToPrimitive,它提供了一个简单的接口来执行数字转换。

请注意,cast(x)会返回Option<T>;如果None无法在目标类型中表示,则会返回x。我在这里使用unwrap()因为在您的情况下,根据您的描述,无法正确转换值可能是一个编程错误,因此失败的任务感觉更合适。也可以直接写cast(x)

if x >= S::zero() { num::cast(x) }
...

在这种情况下,check()不仅会在其参数为负数时返回None,而且如果无法将参数转换为结果类型,也会返回{{1}}。