2015-09-27 2 views
0

У меня возникли проблемы с пониманием того, как работать с чертами и владельцами. Ниже приведен пример:Невозможно вызвать функцию со ссылкой на тип, реализующий признак

struct X([u8; 4]); 

impl X { 
    pub fn get(&self, n: usize) -> u8 { 
     self.0[n] 
    } 
} 

fn f1(x: &X) { 
    println!("{}", x.get(1)); 
    f2(&x); 
} 

fn f2(x: &X) { 
    println!("{}", x.get(2));  
} 

fn main() { 
    let z1 = X([1u8, 2u8, 3u8, 4u8]); 
    f1(&z1); 
} 

Но когда я пытаюсь создать черту (здесь XT) с get:

trait XT { 
    fn get(&self, n: usize) -> u8; 
} 

struct X([u8; 4]); 

impl XT for X { 
    fn get(&self, n: usize) -> u8 { 
     self.0[n] 
    } 
} 

fn f1<T: XT>(x: &T) { 
    println!("{}", x.get(1)); 
    f2(&x); 
} 

fn f2<T: XT>(x: &T) { 
    println!("{}", x.get(2));  
} 

fn main() { 
    let z1 = X([1u8, 2u8, 3u8, 4u8]); 
    f1(&z1); 
} 

Не удается скомпилировать со следующим сообщением об ошибке:

в признак XT не применяется для типа &T

Он работает, если я меняю f2(&x) на f2(x). Мое предположение заключалось в том, что замена типов по признакам, все будет работать.

ответ

3

Проблема в том, что вы пытаетесь пройти &&T до f2. Это означает, что он ожидает &T для реализации XT, и это не что вы сказали: вы сказали, что T реализует XT.

Вы можете изменить f1 правильно выразить это ограничение, используя пункт where T: XT, for<'a> &'a T: XT, но тогда вы не можете позвонить f1 из main потому &X не реализует XT. Итак, вы идете и добавляете реализацию для , а также и , тогда код работает ... но, честно говоря, проще просто удалить это & и вместо этого позвонить f2(x).

Говоря иначе: просто потому, что тип реализует признак не средних указателей к этому типу также реализации признака.

+0

Но запутанная вещь заключается в том, что она работает нормально в первом случае. (Отказ от ответственности: у меня нет полного представления о Rust, так что я могу ошибаться). Это похоже на очень распространенный сценарий: вы пишете какую-то функцию, которая принимает определенный тип, а затем вы понимаете, что можете использовать их для большего количества вещей. Поэтому вы создаете Trait и заменяете (с некоторым синтаксисом) Type for the Trait в определениях функций. Синтаксис, который делает его работу, не очень эргономичен. – Hernan

+1

@Hernan Он работает в первом случае, потому что 'z1' имеет тип' X', поэтому '& z1' имеет тип' & X'. Когда вы вызываете 'f1', компилятор сообщает, что' & T = & X' поэтому 'T = X'. Когда вы вызываете 'f2' с' & x', он получает '& T = && X', поэтому' T = & X', а '& X' не реализует' XT'. –

+0

Спасибо за объяснение. Я получаю это сейчас. Я бы сказал, что создание синтаксиса для признаков, равных синтаксису типов, было бы более эргономичным, но, я думаю, я пропускаю важные вещи о языке. – Hernan

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