添加const泛型时的“无约束泛型常量”

我将如何添加 const 泛型?假设我有一个 foo 类型:

pub struct foo <const bar: i64> {
    value: f64,
}

我想实现 mul 以便我可以将 2 相乘foo。我想把它bar当作一个维度,所以foo<baz>{value: x} * foo<quux>{value: k} == foo<baz + quux>{value: x * k},如下:

impl<const baz: i64, const quux: i64> Mul<foo<quux>> for foo<baz> {
    type Output = foo<{baz + quux}>;

    fn mul(self, rhs: foo<quux>) -> Self::Output {
        Self::Output {
            value: self.value * rhs.value,
        }
    }
}

我收到一个错误,告诉我我需要{baz+quux}在输出类型的定义中添加一个 where 绑定。这究竟是什么意思,我该如何实施?我在 上找不到任何看似相关的信息where

回答

解决方案

我在你的代码上有一个变化在这里工作:

impl<const baz: i64, const quux: i64> Mul<Foo<quux>> for Foo<baz>
    where Foo<{baz + quux}>: Sized {
    type Output = Foo<{baz + quux}>;

    fn mul(self, rhs: Foo<quux>) -> Self::Output {
        Self::Output {
            value: self.value * rhs.value,
        }
    }
}

我是怎么到那里的

我已经复制了您在没有添加where以下子句的情况下获得的完整错误:

error: unconstrained generic constant
  --> src/main.rs:11:5
   |
11 |     type Output = Foo<{baz + quux}>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
help: try adding a `where` bound using this expression: `where [u8; {baz + quux}]: Sized`

现在,它建议的子句不是很有用,原因之一是:静态大小切片的长度参数必须是 a usize,但我们的值bazquux(及其总和)是i64。我想编译器作者包含了这个特定的建议,因为 const 泛型的主要用例是在类型中嵌入数组大小。我在 GitHub 上打开了一个关于此诊断的问题。

为什么这是必要的?

where一些通用的代码元素---一个功能,类型,性状,或在这种情况下,执行关于子句指定约束---基于所述性状和寿命的一个或多个通用参数,或它们的衍生物,必须满足。许多情况下有等效的简写,但总体要求是完全指定约束。

在我们的情况下,可能表面上看来,这实现工程的任意组合bazquux,但这种情况并非如此,由于整数溢出; 如果我们为两者提供足够大的相同符号的值,则它们的总和不能用 表示i64。这意味着i64在加法下不是封闭的。

我们添加的约束要求两个值的总和在 an 的可能值集合中i64,间接地,通过需要消耗它的类型的东西。因此,对于这两个供给2 ^ 31bazquux是无效的,因为所得到的类型Foo<{baz + quux}>不存在,所以它不可能实现的Sized性状。虽然这在技术上是比我们需要的更严格的约束(Sized比简单存在的类型更强的要求),所有Foo<bar>存在的都实现了Sized,所以在我们的例子中它是相同的。另一方面,在没有约束的情况下,没有where子句,明确的或简写的,指定这个约束。


以上是添加const泛型时的“无约束泛型常量”的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>