Я начал с функцией немного, как это (playground):Как я могу обобщить функцию, которая принимает `& [T]`, так что я все еще могу вызвать ее с помощью литерала bytestring?
fn find <T: Copy> (src: &[T], index: usize) -> T {
// more complex algorithm, involving src goes here
src[index]
}
pub fn main() {
let x = b"abc";
assert_eq!(b'b', find(x, 1));
}
И я хотел бы обобщить так, что я могу использовать любой подходящий тип для src
. Лучшее, что я придумал это (playground):
trait RandomAccess<T> {
fn get_at(&self, index: usize) -> T;
}
impl <T: Copy> RandomAccess<T> for [T] {
fn get_at(&self, index: usize) -> T {
self[index]
}
}
fn find <T: Copy, S: ?Sized + RandomAccess<T>> (src: &S, index: usize) -> T {
// more complex algorithm, involving src goes here
src.get_at(index)
}
pub fn main() {
let x = b"xyz";
assert_eq!(b'y', find(&x[..], 1));
}
Однако, сейчас я не могу просто вызвать find(x, 1)
, я должен создать срез: find(&x[..], 1)
.
Есть ли способ сделать этот общий, но все же можно вызвать find
, как в исходном примере?
Похоже, что в первом примере компилятор ржавчины совершает некоторые хитрости за кулисами и позволяет '&[u8; 3]' быть принужденными к '& [u8]', но не может сделать это во втором примере, потому что он не может точно знаю, что это намерение. Это в основном проблема? –
Я попытался абстрагироваться от Index и некоторых других вещей, но я не убежден, что вам нужно вводить такие абстракции вообще - они, как правило, усложняют вещи без добавленной стоимости. К каким другим типам 'src'' find() 'может относиться? –
ljedrz
Хитрость такова: принуждение срабатывает, если известен тип назначения. Поскольку 'find' использует параметр типа для' src', это не так. – bluss