2014-05-02 3 views
4

Pourquoi les références aux objets trait ne sont-elles pas clonables? Ce code compile:Les références aux objets trait ne sont pas clonables

struct Test; 

fn clone_vec<'a>(v: Vec<&'a Test>) -> Vec<&'a Test> { 
    v.clone() 
} 

fn main() { 
} 

Celui-ci n'a pas:

trait Test { 
    fn do_smt(&self); 
} 

fn clone_vec<'a>(v: Vec<&'a Test>) -> Vec<&'a Test> { 
    v.clone() 
} 

fn main() { 
} 

Erreur:

main3.rs:7:5: 7:14 error: failed to find an implementation of trait std::clone::Clone for &'a Test<no-bounds> 
main3.rs:7  v.clone() 
       ^~~~~~~~~ 

Cependant, Clone trait est mis en œuvre pour tout type de référence, pour autant que je peux voir:

impl<'a, T> Clone for &'a T { 
    /// Return a shallow copy of the reference. 
    #[inline] 
    fn clone(&self) -> &'a T { *self } 
} 

Je ne vois pas pourquoi &'a TestTest est un trait n'est pas clonable. C'est juste un pointeur après tout. Cette restriction interdit, par exemple, d'aller de &[&'a SomeTrait] à Vec<&'a SomeTrait>, ce qui ressemble à une conversion évidente, ou de cloner un Vec<&'a SomeTrait>, comme dans l'exemple.

Ceci est très étrange pour autant que je puisse mettre en œuvre moi-même clone_vec(), sans Clone:

fn clone_vec<'a>(v: Vec<&'a Test>) -> Vec<&'a Test> { 
    let mut result = Vec::new(); 
    for &e in v.iter() { 
     result.push(e); 
    } 
    result 
} 

Répondre

4

Clone est un trait de bibliothèque normale, et nécessite des implémentations normales (bibliothèque), pour tous les types. Par exemple, Clone est mis en œuvre pour &Tright here, sous la forme:

impl<'a, T> Clone for &'a T { 
    /// Return a shallow copy of the reference. 
    #[inline] 
    fn clone(&self) -> &'a T { *self } 
} 

Par conséquent, tout de la forme &T est en mesure Clone ... où T un type de béton. Et c'est le clincher: &Trait n'est pas (encore) un type de la forme &T avec T = Trait (mais plutôt un type "atomique"/primitif qui ne peut pas être séparé en parties), donc il n'est pas couvert par impl.

Nous avons besoin de types de taille dynamique (DST) pour que le compilateur puisse raisonner sur le passage de Trait comme un paramètre générique (Nick Cameron est actuellement à l'œuvre dans certaines parties de l'implémentation DST). j'espère arriver bientôt).

Vous pouvez cependant implémenter manuellement Clone pour vos traits d'intérêt, par ex. les travaux suivants: bien

trait Foo {} 

impl<'a> Clone for &'a Foo { 
    fn clone(&self) -> &'a Foo { 
     *self 
    } 
} 

Cependant, il ne fonctionne que pour les caractères définis dans votre caisse actuelle, ou bien le compilateur a des préoccupations au sujet de la cohérence (par exemple l'évolution Foo à Eq dans la impl causes ci-dessus error: cannot provide an extension implementation where both trait and type are not defined in this crate).

+0

C'est ce que je soupçonnais. Je vais attendre l'heure d'été. Il semble que ce sera un changement spectaculaire, tant de nouvelles fonctionnalités qui facilitent la vie :) merci beaucoup! –

Questions connexes