expected struct `Vec3d`, found type parameter `u32` when implmenting the Mul trait for a custom struct

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

expected struct `Vec3d`, found type parameter `u32` when implmenting the Mul trait for a custom struct

问题

我正在尝试为 Vec3d 结构实现 Mul 特性。我想要 mul 函数将 Vec3d 的每个元素与一个数字相乘并返回一个 Vec3d。但是我遇到了以下错误:

error[E0053]: method `mul` has an incompatible type for trait
  --> src\vec_3d.rs:26:21
   |
23 | impl<u32> Mul for Vec3d<u32> {
   |      --- this type parameter
...
26 |     fn mul(self, t: u32) -> Self::Output {
   |                     ^^^
   |                     |
   |                     expected struct `Vec3d`, found type parameter `u32`
   |                     help: change the parameter type to match the trait: `Vec3d<u32>`
   |
   = note: expected fn pointer `fn(Vec3d<_>, Vec3d<u32>) -> Vec3d<_>`
              found fn pointer `fn(Vec3d<_>, u32) -> Vec3d<_>`

我的代码如下:

use std::ops::Add;
use std::ops::Mul;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Vec3d<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}
impl<u32> Mul for Vec3d<u32> {
    type Output = Self;

    fn mul(self, t: u32) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.x * t,
            z: self.x * t,
        }
    }
}

我最初是这样写的,使用通用类型参数 T

impl<T: Mul<Output = T>> Mul for Vec3d<T> {
    type Output = Self;

    fn mul(self, t: T) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.x * t,
            z: self.x * t,
        }
    }
}

我在一些示例和其他问题中看到过这样的写法。有什么问题,以及如何正确实现它呢?

英文:

I am trying to implement the Mul trait for the Vec3d struct. I want the mul function to multiply each element of Vec3d by a number and return a Vec3d. However I am getting faced with this error:

error[E0053]: method `mul` has an incompatible type for trait
  --> src\vec_3d.rs:26:21
   |
23 | impl<u32> Mul for Vec3d<u32> {
   |      --- this type parameter
...
26 |     fn mul(self, t: u32) -> Self::Output {
   |                     ^^^
   |                     |
   |                     expected struct `Vec3d`, found type parameter `u32`
   |                     help: change the parameter type to match the trait: `Vec3d<u32>`
   |
   = note: expected fn pointer `fn(Vec3d<_>, Vec3d<u32>) -> Vec3d<_>`
              found fn pointer `fn(Vec3d<_>, u32) -> Vec3d<_>`

My code looks like this:

use std::ops::Add;
use std::ops::Mul;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Vec3d<T> {
    pub x: T,
    pub y: T,
    pub z: T,
}
impl<u32> Mul for Vec3d<u32> {
    type Output = Self;

    fn mul(self, t: u32) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.x * t,
            z: self.x * t,
        }
    }
}

I had this originally with the generic type parameter T:

impl<T: Mul<Output = T>> Mul for Vec3d<T> {
    type Output = Self;

    fn mul(self, t: T) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.x * t,
            z: self.x * t,
        }
    }
}

I have seen this be done the same way in some examples and other questions. What is wrong and how I can implement this the correct way?

答案1

得分: 1

这几段代码主要是关于Rust中的乘法操作符(Mul)的示例和说明,以下是已翻译的部分:

  • "This is nearly the same as the example on the Mul documentation: Multiplying vectors by scalars as in linear algebra"
  • "Mul has a default generic, which you can see in the trait definition:"
  • "This offers convenience since most implementers of Mul will be multiplying against Self. You aren't, so you need to specify the generic:"
  • "To make this fully generic, you might try this:"
  • "However, since you're using a single T 3 times, you would need to restrict it to Clone or Copy. The usual way to get around this is to implement Mul` for references:"
  • "Then you probably want a non-reference version for when the type implements Copy:"
  • "But even better, you can do both of those in one impl:"
  • "When R is &T you cover the first impl, and when R is T and Copy you cover the second impl. & references are always Copy."
  • "Another common thing to do is implement Mul for every integer type, which allows you more control over the implementation, for example if you wanted to optimize them for certain sized integers."

请注意,这些是代码和代码注释的翻译,没有额外的信息。

英文:

This is nearly the same as the example on the Mul documentation: Multiplying vectors by scalars as in linear algebra

Mul has a default generic, which you can see in the trait definition:

pub trait Mul<Rhs = Self> {

This offers convenience since most implementers of Mul will be multiplying against Self. You aren't, so you need to specify the generic:

impl Mul<u32> for Vec3d<u32> {
    type Output = Self;

    fn mul(self, t: u32) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.y * t,
            z: self.z * t,
        }
    }
}

To make this fully generic, you might try this:

impl<T: Mul<Output = T>> Mul<T> for Vec3d<T>

However, since you're using a single T 3 times, you would need to restrict it to Clone or Copy. The usual way to get around this is to implement Mul for references:

impl<'a, T> Mul<&'a T> for Vec3d<T>
where
    T: Mul<&'a T, Output = T>,
{
    type Output = Self;

    fn mul(self, t: &'a T) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.y * t,
            z: self.z * t,
        }
    }
}

Then you probably want a non-reference version for when the type implements Copy:

impl<T> Mul<T> for Vec3d<T>
where
    T: Mul<Output = T> + Copy,
{
    type Output = Self;

    fn mul(self, t: T) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.y * t,
            z: self.z * t,
        }
    }
}

But even better, you can do both of those in one impl:

impl<T, R> Mul<R> for Vec3d<T>
where
    R: Copy,
    T: Mul<R, Output = T>,
{
    type Output = Self;

    fn mul(self, t: R) -> Self::Output {
        Self {
            x: self.x * t,
            y: self.y * t,
            z: self.z * t,
        }
    }
}

When R is &T you cover the first impl, and when R is T and Copy you cover the second impl. & references are always Copy.

Another common thing to do is implement Mul for every integer type, which allows you more control over the implementation, for example if you wanted to optimize them for certain sized integers.

huangapple
  • 本文由 发表于 2023年2月18日 03:23:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75488482.html
匿名

发表评论

匿名网友

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

确定