2014-09-25 253 views
3

我想以通用的方式检查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 } 
} 

功能时,我敢肯定,ST都是整数类型为check()所有使用什么方法?编译器会拒绝我的代码抱怨error: non-scalar cast: `S` as `T`

回答

4

更新了锈的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::traits::NumCastnum箱子,这是为所有基本类型来实现,并提供其转换为这些类型的东西,它实现num::ToPrimitive的静态方法。箱子还提供了一个功能,num::cast(),它提供了一个简单的界面来执行数字转换。

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

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

在这种情况下check()将返回None不仅当其参数为负,而且如果它是不可能的参数转换为结果类型。

+0

这正是我一直在寻找的! – nodakai 2014-09-26 00:10:17

+0

不幸的是,不再有'std :: num :: NumCast'和'ToPrimitive'特性,我不确定它们是否被任何东西所取代。事情发生了相当大的变化 – Ponkadoodle 2015-11-18 09:05:33

+0

@Wallacoloo的确,大部分数字特征都从'std'中移除。其中一些,包括那些与转换有关的,被转移到了编号。我会尽快更新答案。 – 2015-11-18 09:10:53