【问题标题】:Can I make this assertion generic in Rust?我可以在 Rust 中使这个断言通用吗?
【发布时间】:2016-05-31 02:40:18
【问题描述】:

我正在尝试断言,其他人的 crate 中的函数返回的类型足够大,如果他们将代码更改为仍然可以的代码,我不想更改我的代码。

这是我正在尝试做的事情的简化版本 (playground):

const NANOSECONDS_IN_DAY:f64 = 8.64E13;
trait HasMax<T> {
    fn max_value() -> T;
}
fn max_of<T:HasMax>(_: &T) -> T {
    T::max_value()
}
fn main() {
    let mv = max_of(&1f64);
    assert!(mv > NANOSECONDS_IN_DAY, "type is too small");
}

但是我收到以下错误:

<anon>:5:13: 5:19 error: wrong number of type arguments: expected 1, found 0 [E0243]
<anon>:5 fn max_of<T:HasMax>(_: &T) -> T {
                     ^~~~~~

【问题讨论】:

  • 如果我们假设另一个 crate 从 f64 切换到 u64,即使示例代码已编译,它也会尝试将 u64f64 进行比较,这不起作用。除此之外,可能其他 crate 不知道 HasMax,因此本地 crate 必须为各种类型实现它,这意味着如果类型发生更改,本地代码必须添加新实现。我错过了什么吗?
  • 也许我遗漏了一些关于特征的东西,另一个板条箱现在返回一个 i64,(我忘记在我的示例代码中转换以处理 &gt; 不工作)和 i64(和其他原始数字类型)实现::max_value。所以我认为这应该可行。
  • 原始数字类型实现 max_value — 当 API 更改为返回 struct Time(u64, u64) 时,您希望发生什么?
  • 那么它不会编译,但是虽然它仍然是一个原始的数字类型并且说类型继续实现 max_value 设置和忘记它会很好。即使它不完美,它也能让我长寿。

标签: generics rust traits


【解决方案1】:

尽管您正在使用的库中未来未知的重大 API 更改,但试图让您的代码正常工作充其量是错误的。简短的回答是,如果您正在使用的库的 API 发生变化,最好让您的代码编译失败,而不是以更微妙或难以检测的方式失败。但我可以回答为什么您的代码无法编译。

问题在于您的特征定义,它使用了泛型。你的特质应该是HasMax,而不是HasMax&lt;T&gt;

const NANOSECONDS_IN_DAY:f64 = 8.64E13;
trait HasMax {
    fn max_value() -> Self;
}
fn max_of<T:HasMax>(_: &T) -> T {
    T::max_value()
}
impl HasMax for f64 {
    fn max_value() -> Self {
        std::f64::MAX
    }
}
fn main() {
    let mv = max_of(&1f64);
    assert!(mv > NANOSECONDS_IN_DAY, "type is too small");
}

【讨论】:

  • 另外,我要指出你并不真正需要max_of 函数,因为它只需要你创建一个似乎没有用于其他任何东西的值。相反,您可以致电let mv = &lt;f64 as HasMax&gt;::max_value()。另请参阅 size_ofsize_of_val 了解并行概念。
  • 是的,我同意。整个事情有点过度设计了。
  • 这表明了另一种方法,assert!(std::mem::size_of_val(api::function()) &lt; 6, "type is too small");
  • @CamdenNarzt:这不是我们想要的,因为我们想知道值的范围,而不是用于表示值的存储量。
  • 据我所知范围至少为 2^(bytes*8-1)
【解决方案2】:
extern crate num;
extern crate time;

#[cfg(test)]
mod tests {
    use num::Bounded;
    use time::{self,Tm};
    #[test]
    fn size_test() {
        let NANOSECONDS_IN_DAY:f64 = 8.64E13;
        fn max_of<T:Bounded>(_: T) -> T {
            T::max_value()
        }
        let type_v = time::Duration::zero().num_nanoseconds().unwrap();
        let mv = max_of(type_v);
        assert!(mv as f64 > NANOSECONDS_IN_DAY, "type is too small");
    }
}

这行得通。

【讨论】:

    猜你喜欢
    • 2021-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多