在 Rust 中,我如何限制泛型 T 以允许取模?

In Rust, how can I restrict a generic T to allow modulus?

作为一个exercism exercise,我目前正在尝试根据值是否为偶数来过滤迭代器以生成新的迭代器。

我的函数目前看起来像:

pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T>
    where T: std::ops::Rem<Output = T>
{
    iter.filter(|x| x % 2 != 0)
}

Playground

但这不会编译,因为:

error[E0369]: cannot mod `&T` by `{integer}`
 --> src/lib.rs:4:23
  |
4 |     iter.filter(|x| x % 2 != 0)
  |                     - ^ - {integer}
  |                     |
  |                     &T
  |
help: consider further restricting this bound
  |
2 |     where T: std::ops::Rem<Output = T> + std::ops::Rem<Output = {integer}>
  |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

但是,我知道我不能简单地将其更改为

pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T>
    where T: std::ops::Rem<Output = T> + std::ops::Rem<Output = {integer}>
{
    iter.filter(|x| x % 2 != 0)
}

Playground

因为编译失败:

error: cannot constrain an associated constant to a value
 --> src/lib.rs:2:56
  |
2 |     where T: std::ops::Rem<Output = T> + std::ops::Rem<Output = {integer}>
  |                                                        ------^^^---------
  |                                                        |        |
  |                                                        |        ...cannot be constrained to this value
  |                                                        this associated constant...

我隐约知道一些“Num”特征,但练习似乎不接受需要通过 Cargo.toml 导入依赖项的答案,所以我正在寻找 native/built-in解决方案。

我有什么想法可以让这项工作成功吗?

(P.S。我现在发现我误解了这个练习,其中“偶数”描述的是枚举索引,而不是值……但没关系。我仍然想知道whether/how 这可以工作。)

没有第三方库的最简单方法是将常量显式转换为T

use core::convert::TryFrom;

pub fn evens<T>(iter: impl Iterator<Item = T>) -> impl Iterator<Item = T>
    where T: Eq + Copy + std::ops::Rem<Output=T> + TryFrom<i32>
{
    let zero = T::try_from(0).ok().unwrap();
    let two = T::try_from(2).ok().unwrap();
    iter.filter(move |x| *x % two != zero)
}