首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么需要一个特征来约束类型参数?

为什么需要一个特征来约束类型参数?
EN

Stack Overflow用户
提问于 2017-07-06 18:35:16
回答 2查看 131关注 0票数 0

为什么在下面的代码中需要这个特征?没有特征的注释变体无法编译,即使它看起来具有相同的可用信息。

代码语言:javascript
复制
trait ReliabilityConstructor<T> {
    fn new(a: T) -> Reliability;
}

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Reliability {
    alpha: i8,
}

//impl<T> Reliability
impl<T> ReliabilityConstructor<T> for Reliability
where
    f64: std::convert::From<T>,
{
    fn new(a: T) -> Reliability {
        let mut a_f64 = f64::from(a);
        a_f64 = if a_f64 < -1f64 {
            -1f64
        } else if a_f64 > 1f64 {
            1f64
        } else {
            a_f64
        };
        Reliability {
            alpha: (100f64 * a_f64) as i8,
        }
    }
}

fn main() {
    println!("{:?}", Reliability::new(-1));
}

当注释行未注释时:

代码语言:javascript
复制
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> src/main.rs:10:6
   |
10 | impl<T> Reliability
   |      ^ unconstrained type parameter
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-06 18:47:20

只需将特征从From更改为Into (因为From<T> for U暗示Into<U> for T) -意图就更明确了:

代码语言:javascript
复制
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Reliability {
    alpha: i8,
}

impl Reliability {
    fn new<T: Into<f64>>(a: T) -> Reliability { // <T> is only here
        let mut a_f64: f64 = a.into(); // into() is used here
        a_f64 = if a_f64 < -1f64 {
            -1f64
        } else if a_f64 > 1f64 {
            1f64
        } else {
            a_f64
        };
        Reliability { alpha: (100f64 * a_f64) as i8 }
    }
}

fn main() {
    println!("{:?}", Reliability::new(-1));
}
票数 3
EN

Stack Overflow用户

发布于 2017-07-06 18:39:47

这是因为您在特征定义上定义了类型参数,而不是在结构定义上。为了摆脱这个特征,你需要将T移到结构本身:

代码语言:javascript
复制
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Reliability<T> {
    alpha: i8,
}

impl<T> Reliability<T>
where
    f64: std::convert::From<T>,
{
    fn new(a: T) -> Reliability<T> {
        let mut a_f64 = f64::from(a);
        a_f64 = if a_f64 < -1f64 {
            -1f64
        } else if a_f64 > 1f64 {
            1f64
        } else {
            a_f64
        };
        Reliability {
            alpha: (100f64 * a_f64) as i8,
        }
    }
}

fn main() {
    println!("{:?}", Reliability::new(-1));
}

也就是说,这引发了一个不同的问题-- Reliability实际上并没有在定义或实现中使用T,所以它会因为这个错误而失败:

代码语言:javascript
复制
error[E0392]: parameter `T` is never used
 --> src/main.rs:2:20
  |
2 | struct Reliability<T> {
  |                    ^ unused type parameter
  |
  = help: consider removing `T` or using a marker such as `std::marker::PhantomData`

您的问题是,您不是在尝试约束结构,而是试图约束方法。在这种情况下,这就容易多了!

代码语言:javascript
复制
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Reliability {
    alpha: i8,
}

impl Reliability {
    fn new<T>(a: T) -> Reliability
    where
        f64: std::convert::From<T>,
    {
        let mut a_f64 = f64::from(a);
        a_f64 = if a_f64 < -1f64 {
            -1f64
        } else if a_f64 > 1f64 {
            1f64
        } else {
            a_f64
        };
        Reliability {
            alpha: (100f64 * a_f64) as i8,
        }
    }
}

fn main() {
    println!("{:?}", Reliability::new(-1));
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44946535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档