2015-09-04 2 views
1

У меня есть этот код (in playground):Matching общий параметр для другого обобщенного параметра с осущ

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  
    } 
} 

То, что я хочу сделать, это сохранить подпись give функции признака Trait и в то же время для реализации признака Trait для общей структуры Struct.

, но я получаю эту ошибку

<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, который выбран в Implementor, не вызывающего абонента.

Другим вариант не использовать вместо связанных типов:

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

Спасибо за ответ, да, это было бы решением, однако реализация этого изменяет подпись функции 'give'. Если честно, то, что я хочу, не использует дженерики по признаку 'Trait', поскольку это приводит к использованию дженериков в других чертах, которые зависят от него, чего я хочу избежать. – Otobo

+0

Наконец, в моем случае, используя ваше предложение в сочетании с объявлением общей черты «Trait» как «Self», когда я определяю другие зависящие черты, решал проблему. Пример определения другой черты в зависимости от 'Trait': ' trait NewTrait: Trait {...} ' Однако я буду ждать другого решения, на случай, если кто-то другой не сможет использовать' Self' в определениях признаков , – Otobo

+0

Я добавил другое решение, используя связанные типы. –

Смежные вопросы