2016-03-04 15 views
7

Ich habe ein Merkmal Trait mit einem zugehörigen Typ Trait::Associated. Ich versuche, das Merkmal zu gebunden durch die Forderung, dass sie durch ihren zugehörigen Typen Wende sein, wie hier gezeigt:Merkmal gebunden mit zugehörigem Typ als Parameter

use std::ops::Index; 

pub trait Trait: Index<Trait::Associated> { 
    type Associated; 
} 

Allerdings wirft der Compiler, dass der zugehörige Typ ist mehrdeutig

error: ambiguous associated type; specify the type using the syntax <Type as Trait>::Associated [E0223]

pub trait Trait: Index<Trait::Associated> 
         ^~~~~~~~~~~~~~~~~ 

ich auch versucht, Bezug nehmend auf den zugehörigen Typ als Self::Associated, aber verständlicherweise dann protestiert der Compiler über einen zyklischen Bezug zwischen dem Typ und dem Merkmal.

Schließlich habe ich auch versucht, explizit die Umsetzung Index für Trait:

pub trait Trait { 
    type Associated; 
} 

impl<T: Trait> Index<T::Associated> for T { 
    type Output = str; 
    fn index(&self, associated: T::Associated) -> &'static str { "sup" } 
} 

Leider das auch nicht:

error: type parameter T must be used as the type parameter for some local type (e.g. MyStruct<T>); only traits defined in the current crate can be implemented for a type parameter

Versuche ich etwas unvernünftig, hier zu tun? Gibt es einen Weg, etwas Ähnliches zu erreichen, ohne Generika zu verwenden?

Playpen link.

Antwort

9

Sie sind nah, ganz in der Nähe.

Die Antwort ist einfach: die Trait einfach nicht davon ausgehen, dass jede Bezugnahme auf Trait in ihrer Definition auf den aktuellen Typen bezieht, nachdem alles, was Sie könnte auch auf andere Arten der Umsetzung Trait auch beziehen möchte.

Um anzugeben, dass Sie einen bestimmten Typ möchten, sollten Sie den Hinweis beachten: Verwenden Sie <Type as Trait>::Associated, wobei Type der aktuelle Typ ist.

Also, bei der Definition der Trait, wie beziehen Sie sich auf den konkreten Typ, für den es instanziiert wird? Sie verwenden Self!

Die Lösung, so ist:

pub trait Trait: Index<<Self as Trait>::Associated> { 
    type Associated; 
} 
+0

Danke, das hat perfekt funktioniert! Übrigens, gibt es eine Möglichkeit, meinen dritten Versuch zum Laufen zu bringen (der, wo die Merkmalsdefinition und der "Impl" -Block getrennt sind)? Wenn ich versuche, 'Self' in der 'impl'-Zeile zu verwenden, beklagt sich rustc. – Jean

+1

@Jean: die Syntax wäre 'impl Index < :: Associated> für T ', aber es gibt ein Kohärenzproblem hier. Sie können nicht nur ein "Merkmal" aus einer anderen Kiste für einen Typ Ihrer eigenen Kiste implementieren (um zu vermeiden, dass mehrere Personen widersprüchliche Implementierungen eines bestimmten Merkmals für einen bestimmten Typ bereitstellen). Hier beschränkt sich 'T' nicht auf die Arten Ihrer Kiste ... also ist es verboten. –

1

Ich denke, die folgende Semantik liefern Sie wollen, den Ansatz des zweiten Versuchs nehmen.

pub trait Trait { 
    type Associated; 
} 

impl<T> Index<T> for Trait<Associated=T> { 
    type Output=str; 
    fn index(&self, associated: T) -> &'static str { "sup" } 
} 
Verwandte Themen