2015-09-04 81 views
1

我有這樣的代碼(in playground):匹配一個泛型參數到IMPL的另一個泛型參數

trait Limit {} 

pub trait Trait 
{ 
    fn give<T>(&self, x: T) -> T 
    where T: Limit; 
} 

struct Struct<T: Limit> {field: T} 

impl<T> Trait for Struct<T> 
    where T: Limit 
{ 
    fn give<S>(&self, x: S) -> S 
    where S: Limit 
    { 
     self.field 
     //interacts with x parameter and gives an "S: Limit" result  
    } 
} 

我想要做的就是保持性狀Traitgive功能的簽名,並在同一時間爲通用結構Struct實現特徵Trait

,但我得到這個錯誤

<anon>:17:8: 17:14 error: mismatched types: 
expected `S`, 
    found `T` 
(expected type parameter, 
    found a different type parameter) [E0308] 
<anon>:17  self.field  
       ^~~~~~ 

我想用我在這個question其相關的參數與通用參數匹配看見,所以我改變:

fn give<S>(&self, x: S) -> S 
    where S: Limit 

到:

fn give<S = T>(&self, x: S) -> S 
    where S: Limit 

我沒有得到關於此語法的錯誤,但它wa解決上面的錯誤。

有什麼辦法可以實現我想要做的事情嗎?

而一個側面的問題,在這種情況下究竟做什麼<S = T>

回答

1

正如你所寫,你的Trait的實現必須實現give的方式適用於任何類型的調用者希望。另一方面,您的give執行Struct<T>只適用於特定類型,T

如何讓特質本身是通用的,而不是方法?

pub trait Trait<T> where T: Limit { 
    fn give(&self, x: T) -> T; 
} 

impl<T> Trait<T> for Struct<T> where T: Limit { 
    fn give(&self, x: T) -> T 
    { 
     self.field // does not compile, you can't give away one of your fields 
        // unless you mem::replace() it with another value 
    } 
} 

這樣,Trait<T>實現只適用於由實施者,而不是調用選擇特定類型T

另一種選擇是使用相關的類型,而不是:

pub trait Trait { 
    type T: Limit; 

    fn give(&self, x: Self::T) -> Self::T; 
} 

impl<T> Trait for Struct<T> where T: Limit { 
    type T = T; 

    fn give(&self, x: T) -> T 
    { 
     self.field 
    } 
} 

這裏,Trait不再是通用的,但Struct仍然是通用的,並且Struct每個實例實現相同的Trait特質。

+0

感謝您的回答,是的,這將是一個解決方案,但是實現這個更改'給予'功能的簽名。 說實話,我想要的不是在trait特質上使用泛型,因爲這會導致在我想避免的其他依賴於特徵的特徵中使用泛型。 – Otobo

+0

最後,在我的案例中,當我定義其他依賴特質時,將你的建議與聲明特質'Trait'的通用名稱聯合起來解決了這個問題。 定義其他性狀取決於'特性'的示例: '特性NewTrait:特質 {...}然而,我會等待另一種解決方案,以防萬一其他人不能在特徵定義中使用「Self」 。 – Otobo

+0

我已經添加了另一種解決方案,使用關聯的類型。 –