簡體   English   中英

如何在特征綁定中指定`std :: ops :: Mul`的預期結果?

[英]How do I specify the expected result of a `std::ops::Mul` in a trait bound?

我有:

use std::ops::{Add, Div, Mul, Neg, Sub};

pub trait Hilbert: Add + Sub + Mul + Div + Neg + Mul<f64> + Div<f64> + Sized {
    fn dot(&self, other: &Self) -> f64;
    fn magnitude(&self) -> f64;
}

fn g<T: Hilbert>(x: T) -> f64 {
    return (x * 2.0).dot(x);
}

...產生:

error[E0599]: no method named `dot` found for type `<T as std::ops::Mul<f64>>::Output` in the current scope
 --> src/main.rs:9:22
  |
9 |     return (x * 2.0).dot(x);
  |                      ^^^
  |
  = help: items from traits can only be used if the trait is implemented and in scope
  = note: the following trait defines an item `dot`, perhaps you need to implement it:
          candidate #1: `Hilbert`

我的解釋是,Rust無法保證具有特征Hilbert T類型具有std::ops::Mul的實現,其::Output類型等於T (一個Hilbert )。

但是我知道(和/或希望要求)所有Hilbert都是這種情況,因此可以編寫g()類的函數。

我會覺得IMPL std::ops::Mul::OutputHilbert

impl<T: Hilbert> Mul<f64> for T {
    type Output = T;
}

...但是這同時存在一些問題,即(a)我無法“部分實現”特征,並且將被迫為所有Hilberts生成函數Mul::mul()的泛型實現,但實際實現是Mul::mul()取決於Hilbert的具體實現; (b)似乎根本不允許我寫這個特征:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
  --> src/main.rs:12:1
   |
12 | / impl<T: Hilbert> Mul<f64> for T {
13 | |     type Output = T;
14 | | }
   | |_^

我如何說服Hilbert * f64 > Hilbert必須持有的Rust?

我如何說服Hilbert * f64 > Hilbert必須持有的Rust?

您添加一個以<T as Mul<f64>>::Output: Hilbert綁定的特征。 但是,這樣做將揭示設計中的其他問題:

  1. Hilbert.dot()將第二個參數作為參考,而不是按值。 但是將相關行更改為(x * 2.0).dot(&x)會導致另一個錯誤: “期望的關聯類型,找到的類型參數”
  2. 這是因為您將dot定義為Self ,但是您可能想要乘以Hilbert不同實現。 dot必須是通用的: fn dot<H: Hilbert>(&self, other: &H) -> f64;
  3. 最終,借閱檢查器將命中: (x * 2.0).dot(&x)不允許您使用x兩次,因為mul會按值取值。 您要么必須添加綁定的Mul<&'a Self>才能傳遞參考(這會使用生命周期參數感染您的API),要么使x克隆(我認為可復制並不適用)。

將以上所有結果應用於此可工作的可編譯代碼:

pub trait Hilbert: Add + Sub + Mul + Div + Neg + Mul<f64> + Div<f64> + Sized {
    fn dot<H: Hilbert>(&self, other: &H) -> f64;
    fn magnitude(&self) -> f64;
}

fn g<T: Hilbert + Clone>(x: T) -> f64
where
    <T as Mul<f64>>::Output: Hilbert,
{
    (x.clone() * 2.0).dot(&x)
}

如果由於不同的Hilbert實現不需要交互Hilbert.dot不通用,則代碼可以稍微簡單一些(就特征界限而言):

pub trait Hilbert:
    Add + Sub + Mul + Div + Neg + Mul<f64, Output = Self> + Div<f64, Output = Self> + Sized
{
    fn dot(&self, other: &Self) -> f64;
    fn magnitude(&self) -> f64;
}

fn g<T: Hilbert + Clone>(x: T) -> f64 {
    (x.clone() * 2.0).dot(&x)
}

但是,根據我對希爾伯特變換的了解,后一種情況似乎不太有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM