如何使用 TryFrom 将 usize 转换为 u32?

2023-12-23

我想转换一个usize将变量输入到u32Rust 中的类型化变量。我知道usize变量可能包含大于 2^32 的值,在这种情况下转换应该失败。我正在尝试使用TryFrom特征来执行转换。

这是一个简单的例子(Nightly Rust,):

#![feature(try_from)]
use std::convert::TryFrom;

fn main() {
    let a: usize = 0x100;
    let res = u32::try_from(a);
    println!("res = {:?}", res);
}

代码无法编译,出现以下编译错误:

error[E0277]: the trait bound `u32: std::convert::From<usize>` is not satisfied
 --> src/main.rs:6:15
  |
6 |     let res = u32::try_from(a);
  |               ^^^^^^^^^^^^^ the trait `std::convert::From<usize>` is not implemented for `u32`
  |
  = help: the following implementations were found:
            <u32 as std::convert::From<std::net::Ipv4Addr>>
            <u32 as std::convert::From<u8>>
            <u32 as std::convert::From<char>>
            <u32 as std::convert::From<u16>>
  = note: required because of the requirements on the impl of `std::convert::TryFrom<usize>` for `u32`

我从编译错误中推断出TryFrom<usize> for u32取决于有From<usize> for u32,这对我来说似乎有些奇怪。

我还有其他方法可以利用吗TryFrom转换自usize to u32?如果没有,是否有其他惯用的方法来执行此转换?

我知道我可以使用as关键字,但如果转换出现问题,它不会通知我。此外,我认为我可以编写自己的函数来执行转换,但如果 R​​ust 没有某种惯用的方法来执行此转换,我会感到惊讶。usize and u32毕竟是两种基本类型。


自从创建这个答案以来,决定了 https://github.com/rust-lang/rust/pull/51564实施TryFrom<usize>无论当前平台如何,始终考虑到失败的可能性。原始代码现在可以在 Rust 1.34 中成功编译。

原答案

having TryFrom<usize> for u32取决于有From<usize> for u32,这对我来说有点奇怪

这是因为有一个全面的实施TryFrom对于任何实现From:

impl<T, U> TryFrom<U> for T
where
    T: From<U>,
{
    type Error = !;
}

正如您所提到的,由于 Rust 支持本机整数长度为 16、32 或 64 位的平台,因此具有这样的实现From / Into在其中一些平台上不会是无损的。

出现此错误是因为没有直接实现TryFrom / TryInto对于这些类型。这是因为这些特征的用户更喜欢在适合平台的情况下实现万无一失(type Error = !).

有一个单独的跟踪问题 49415 https://github.com/rust-lang/rust/issues/49415专门来决定这个问题。

我认为我可以编写自己的函数来进行转换

是的,这就是你应该做的。像这段未经测试的代码:

use std::u32;

struct SomeError;

// usize is a u16 or u32, which always fits in a u32
#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
fn my_thing(a: usize) -> Result<u32, SomeError> {
    Ok(a as u32)
}

// usize is a u64, which might be too big
#[cfg(target_pointer_width = "64")]
fn my_thing(a: usize) -> Result<u32, SomeError> {
    if a > u32::MAX as usize {
        Err(SomeError)
    } else {
        Ok(a as u32)
    }
}

如果 Rust 没有一些惯用的方法来进行这种转换,我会感到惊讶。usize and u32毕竟是两种基本类型。

问题是usize并不是真正的“基本”类型,因为它会根据目标平台改变大小。得到这个正确的、高性能的and符合人体工程学并不容易。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 TryFrom 将 usize 转换为 u32? 的相关文章

随机推荐