2016-10-12 3 views
9

私は論理的に、それは問題ではありませんので、そのすべての参照型(f64&'a f64、および&'a mut f64)以上(私の場合f64で)タイプTに一度、この形質を実装したい特性すべての参照型に対してイテレータの特性を一般的に実装する方法はありますか?

trait Foo<T> : Iterator<Item=T> { 
    fn bar(&mut self) -> f64; 
} 

を持っています。

私は現在

impl<T: Iterator<Item = f64>> Foo<f64> for T { 
    fn bar(&mut self) -> f64 { 
     // duplicated code 
    } 
} 

impl<'a, T: Iterator<Item = &'a f64>> Foo<&'a f64> for T { 
    fn bar(&mut self) -> f64 { 
     // duplicated code 
    } 
} 

impl<'a, T: Iterator<Item = &'a mut f64>> Foo<&'a mut f64> for T { 
    fn bar(&mut self) -> f64 { 
     // duplicated code 
    } 
} 

は重複せずにこれを実現するための良い方法はありますか?

+0

私はすべてを1つの方法で実行する方法は正確には分かりません。あなたが何をしているのか正確に知らなければ、複製されたコードを 'Borrow'特性を使ってヘルパー関数に移動させることができます。 [このプレイペンは解決策を提供する可能性があります](https://play.rust-lang.org/?gist=296e500aa94741cb59af262454f5f413&backtrace=0)。 –

答えて

7

これにはBorrowの特性を使用できます。ドキュメントページの実装者を見ると、最初の3つがここで関連します。つまり、f64&'a f64、および&'a mut f64はすべてBorrow<f64>を実装しています。イテレータによって生成された各値に対してborrowメソッドを呼び出して、&f64を取得する必要があります。ところで

use std::borrow::Borrow; 

impl<T> Foo<T::Item> for T 
    where T: Iterator, 
      T::Item: Borrow<f64> 
{ 
    fn bar(&mut self) -> f64 { 
     unimplemented!() 
    } 
} 

、それは実際に特性上の型パラメータを定義するために意味をなすと同時に、その型パラメータとsupertraitの関連するタイプ間の制約を入れていません。タイプTIteratorの1つの実装しか持つことができないため、多くの異なるFoo<T>特性を実装できることを示す型パラメータにもかかわらず、Fooの実装を1つしか持てません。したがって、Fooのtypeパラメータは完全に冗長です(typeパラメータの代わりにsupertraitの関連タイプを使用することができます)。したがって、コードは次のようになります。

use std::borrow::Borrow; 

trait Foo: Iterator { 
    fn bar(&mut self) -> f64; 
} 

impl<T> Foo for T 
    where T: Iterator, 
      T::Item: Borrow<f64> 
{ 
    fn bar(&mut self) -> f64 { 
     unimplemented!() 
    } 
} 
+0

私はランチブレイク中にプレイペーンの仕事でC#の職場でこれをすぐにテストしなければなりませんでした。そのため、文法を正確に理解するのに十分速く考えることができませんでした。私はちょっと正しい道にいたのがうれしい! –

+1

@SimonWhiteheadでは、統合テストの実行中に錆コードを打ち消すことができます。その後、ユニットテストが実行されます。その後、Intellisenseは揺れを描きます。 ;-) – Shepmaster

+1

@Shepmaster haha​​ - 私はそう願っています。真夜中にRustと.NETの間でコンテキストを切り替えるのはちょっと厄介です。私の統合テストが実行されている間にコンテキスト切り替えに5分かかる場合でも、P –

関連する問題