Literals in Trait methods implementing generics

huangapple go评论60阅读模式
英文:

Literals in Trait methods implementing generics

问题

我正在尝试学习在Rust中使用GenericsTraits,并使用num crate编写泛型代码。我得到了以下编译器错误:

6 |         return self.gt(0)
  |                     -- ^ 期望类型参数 `T`,但找到整数

在这个代码块上。

如果我使用num::zero,它可以正常工作。但这会限制它只能使用num crate中定义的符号。我希望它能在trait方法中与任何整数字面量一起工作。如何解决这个问题?

我尝试过0 as Integer,但它不会编译,也尝试过0 as i32等等。

英文:

I'm trying to learn Generics and Traits in Rust and using the num crate to write generic code.
I get the following compiler error

6 |         return self.gt(0)
  |                     -- ^ expected type parameter `T`, found integer

on this code block.

use num::{Integer, zero};

trait CanCompareGreater<T: Integer> {
    fn gt(&self, other: T) -> bool;
    fn is_positive(&self) -> bool {
        return self.gt(0)
    }
}

struct MyNumber {
    num: i32,
}

impl CanCompareGreater<i32> for MyNumber
{
    fn gt(&self, other: i32) -> bool {
        self.num > other
    }
}

fn main() {
    let n = MyNumber {num: 5};
    println!("{}", n.is_positive());
}

If I use num::zero it works correctly.
But that restricts it to symbols defined in the num crate. I want it to work with any integer literal in the trait methods.
How would I go about doing it ?

I've tried 0 as Integer which doesn't compile 0 as i32 etc

答案1

得分: 2

更新: drewtato的回答可能比我的更好,因为它提供了基于num::NumCast(我不熟悉的一个trait)的解决方案。但需要注意的是,对于超出范围的值,T::from()会返回None。我们不是在谈论MyNumber的实例num字段中的特定值,而是在谈论作为参数传递给T::from(...)的值。

我会保留我的答案,因为它可能仍然有助于理解为什么OP的示例不起作用。


让我们首先看看这个例子(与泛型或num库无关):

fn abc(a: i32) {
    println!("Called abc with {a}");
}

fn main() { 
    let b = 23 as i16;
    abc(b);
}

编译器会生成以下错误:

error[E0308]: mismatched types
 --> src/main.rs:7:9
  |
7 |     abc(b);
  |     --- ^ expected `i32`, found `i16`

CanCompareGreater::is_positive()中,您尝试调用方法gt,并传递特定类型(如i32)的特定值,而期望一个泛型T: Integer。这不能编译,因为T的类型可能与您尝试传递的特定值的类型不同,然后您会遇到类似上面示例的情况。

英文:

Update: drewtato's answer is probably better than mine, as it provides a solution based on num::NumCast (a trait I wasn't familiar with). A word of caution though: one needs to be aware that for out-of-range values T::from() would return None. We are not talking about the specific value in MyNumber's instance num field, but the value passed as a parameter to T::from(...).

I'll keep my answer below, as it might still be helpful in understanding why the OP's example didn't work.


Let's first take a look at this example (which has nothing to do with generics or the num crate:

fn abc(a: i32) {
    println!("Called abc with {a}");
}

fn main() { 
    let b = 23 as i16;
    abc(b);
}

The compiler emits the following error:

error[E0308]: mismatched types
 --> src/main.rs:7:9
  |
7 |     abc(b);
  |     --- ^ expected `i32`, found `i16`

In CanCompareGreater::is_positive() you are trying to call the method gt by passing some specific value of a specific type (such as i32) where a generic T: Integer is expected. That cannot be compiled, because T's type might happen to be different from the type of the specific value you are trying to pass, and then you'd get in a situation similar to the above example.

答案2

得分: 2

字面数字有自己的推断,与通用推断不同。这种推断不能逃离函数或依赖于泛型,所以你不能在这里使用它。你也不能使用 as,因为它也与泛型推断无关。但有一个模仿 asNumCast 特性。

use num::{Integer, NumCast};

trait CanCompareGreater<T: Integer + NumCast> {
    fn gt(&self, other: T) -> bool;
    fn is_positive(&self) -> bool {
        return self.gt(T::from(4).unwrap())
    }
}

还有一个 num_traits::AsPrimitive,更接近 as,因为它是不会失败的。

英文:

Literal numbers have their own inference going on that's separate from generic inference. This inference can't escape the function or depend on generics, so you can't use it here. You also can't use as since that is also not connected to generic inference. But there's the NumCast trait that mimics as.

use num::{Integer, NumCast};

trait CanCompareGreater&lt;T: Integer + NumCast&gt; {
    fn gt(&amp;self, other: T) -&gt; bool;
    fn is_positive(&amp;self) -&gt; bool {
        return self.gt(T::from(4).unwrap())
    }
}

There's also num_traits::AsPrimitive which is closer to as since it is infallible.

huangapple
  • 本文由 发表于 2023年5月28日 13:08:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350017.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定