我想以一种通用的方式判断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()的所有用法的完整类型时?编译器拒绝我的代码

推荐答案

将任意类型强制转换为任意类型是不可能的,而这正是(几乎)您要做的.在类型约束和转换操作中需要更加具体.

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::NumCast,它是为所有基本类型实现的,并提供了一个静态方法,可以将实现num::ToPrimitive的任何类型转换为这些类型.num crate 还提供了一个函数num::cast::cast(),它提供了一个简单的界面来执行数字转换.

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

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

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

Rust相关问答推荐

为什么函数不接受选项T参数的所有权?

将已知大小的切片合并成一个数组,

为什么要在WASM库中查看Rust函数需要`#[no_mangle]`?

为什么我可以跟踪以前borrow 过的变量?房主在哪里?

带扫描的铁 rust 使用滤镜

通过使用光标拖动角来绕其中心旋转矩形

"value is never read警告似乎不正确.我应该忽略它吗?

在Rust中,如果Result是Err,运行副作用(如日志(log)记录)的惯用方法是什么

告诉Rust编译器返回值不包含构造函数中提供的引用

borrow 是由于对 `std::sync::Mutex>` 的解引用强制而发生的

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

如何在 Rust 中将函数项变成函数指针

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

如何从borrow 的异步代码运行阻塞代码?

Rust中是否可以在不复制的情况下从另一个不可变向量创建不可变向量?

如何在 Rust 中将 Vec> 转换为 Vec>?

如何限制通用 const 参数中允许的值?

了解 Rust 闭包:为什么它们持续持有可变引用?

类型判断模式匹配panic

Rust 异步和 AsRef 未被发送