Каковы лучшие практики для реализации универсального кода, который может быть повторно использован для различных типов владения: & 'T, или Box <T>, или A: T? - PullRequest
0 голосов
/ 09 мая 2018

У меня есть черта T. Я реализую структуру S, которая владеет или сохраняет ссылку на объект, который реализует черту T. Это можно сделать одним из нескольких способов:

  1. struct S<A: T> {
        field: A,
    }
    
  2. struct S<A: T, 'a> {
        field: &'a A,
    }
    
  3. struct S<'a> {
        field: &'a T,
    }
    
  4. struct S {
        field: Box<T>,
    }
    

... и т. Д.

В разных контекстах могут быть полезны разные модели собственности.

Я бы хотел реализовать S таким образом, чтобы его можно было создать любым из следующих способов:

trait T { }
struct A { }
impl T for A { }

fn main() {
    let a = A {};
    let s1 = S::new_owning(a);
    let s2 = S::new_from_ref(&a);
    let s3 = S::new_from_trait_ref(&a as &T);
    let s4 = S::new_from_boxed_trait(Box::new(a));
}

1 Ответ

0 голосов

Это может зависеть от регистра, но когда это возможно, вы должны предпочесть принять значение напрямую (как, например, T: Trait).

Существует аналогичное руководство по API ( C-RW-VALUE ), которое рекомендует интерфейсам принимать параметр T напрямую, а не изменяемую ссылку на значение, которое реализует std::io::Read или std::io::Write. Это работает, потому что Read и Write также реализованы для изменяемых ссылок на произвольные T типы, реализующие эти черты.

Если вы контролируете эту черту, использование того же подхода довольно идиоматично и решает вашу проблему без необходимости использования большого количества функций конструктора.

trait T { }
// generic implementations for references and smart container types follow
impl<'a, U: ?Sized + T> T for &'a U { }
impl<U: ?Sized + T> T for Box<U> { }

struct A { }
impl T for A { }

fn main() {
    let a = A {};
    let s1 = S::new(a);
    let s2 = S::new(&a);
    let s3 = S::new(&a as &T);
    let s4 = S::new(Box::new(a));
}

Смотри также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...