2015-09-04 74 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

我已经添加了另一种解决方案,使用关联的类型。 –