我刚刚发现我自己写了动态断言,它依赖于常数
usize::MAX
。 u128::try_from(letters.len())
.expect("No support for platform with `max pointer value` >= 2**128.")
其中
letters.len()
是 usize
的实例。
相反,我希望我的代码无法在“指针大小 >= 2**128”的罕见(如果存在)平台上编译。
我读过类似的问题(由社区建议)。
它展示了断言指针具体大小的方法。
例如。
#[cfg(not(target_pointer_width = "64"))]
usize::MAX<=u128::MAX && usize::MIN>=u128::MIN
成为 true
就足够了。
经过一番思考,我制定了一个解决方案,无论是在我的脑海中还是在当前测试的具有 x64 架构和 Rust 1.60 的 Debian 上,它都工作得很好。
代码:
const _:()= assert!(usize::BITS<=u128::BITS);
assert!()
还好。 assert!()
自 Rust 1.57.0 起仅在 const 上下文中可用,因此如果您需要支持旧版本,可以使用 static_assertions
crate。这个想法是将 assert!()
替换为以下常量表达式:
const _: [(); 0 - (!(usize::BITS <= u128::BITS)) as usize] = [];
现在,如果表达式的计算结果为
true
,则其否定计算结果为 false
,并且 false as usize
为零。所以我们声明一个零长度数组,一切都很好。
但是,如果表达式的计算结果为
false
,则其否定为 true
和 true as usize == 1
。 0usize - 1usize
溢出 - 这是一个错误。
缺点是它会生成一条非常晦涩的错误消息:
error[E0080]: evaluation of constant value failed
--> src/lib.rs:1:15
|
1 | const _: [(); 0 - (!(usize::BITS > u128::BITS)) as usize] = [];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
(我交换了条件,所以它会是
false
)。