2015-05-25 38 views
6

Tôi có một vấn đề thiết kế, khi sử dụng một cái gì đó như:Làm thế nào để thực hiện một đặc điểm cho một đặc điểm tham số

trait MyTrait<K: OtherTrait> { ... } 

impl<K: OtherTrait, M: MyTrait<K>> AnyTrait for M { ... } 

tôi có thể không thực hiện đặc điểm cho đặc điểm này do E207 lỗi ("tham số kiểu K không bị hạn chế bởi đặc tính impl, kiểu tự, hoặc các vị từ ").

Tìm không có cách nào để thoát khỏi lỗi này, tôi áp dụng this not-so-good-looking workaround (verbose và struct không có giá trị nội tại):

use std::fmt; 
use std::marker::PhantomData; 

pub trait MyTrait<K: fmt::Display> { 
    fn get_some_k(&self) -> Option<K>; 
} 

/* // This is my target impl but results in E207 due to K not constrained 
impl<K: fmt::Display, S: MyTrait<K>> fmt::Display for S { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     write!(f, "{}", self.get_some_k().unwrap()) 
    } 
} */ 
pub struct Ugly<'a, K: fmt::Display, S: 'a + MyTrait<K>>(&'a S, PhantomData<K>); 
impl<'a, K: fmt::Display, S: MyTrait<K>> fmt::Display for Ugly<'a, K, S> { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     write!(f, "{}", self.0.get_some_k().unwrap()) 
    } 
} 

fn main() { } 

Tôi nghĩ rằng không nên có một số cách đẹp hơn để thực hiện một đặc điểm cho các loại hình đặc điểm tham số.

Tôi không tìm thấy ví dụ điển hình trong tiêu chuẩn (ví dụ: không triển khai Display trong các đặc điểm có loại được liên kết như Iterator)?

+0

Chỉ cần nghĩ rằng tôi muốn đề cập đến tôi đang chạy vào cùng một vấn đề chính xác, tuy nhiên tôi không có sự sang trọng của gói chăn impl trong một 'Ugly', như' MyTrait' là một đặc điểm công khai tiếp xúc với người dùng, và yêu cầu họ sử dụng 'Ugly' triệt để phá hủy API bằng cách thêm sự phức tạp không cần thiết. – mindTree

+0

Bản sao có thể có của [Cung cấp triển khai thực hiện chăn nuôi cho một đặc điểm tùy chỉnh] (http://stackoverflow.com/questions/32430659/providing-blanket-trait-implementations-for-a-custom-trait) – wimh

Trả lời

2

Here’s an implementation using associated types (có nghĩa là bạn chỉ có thể thực hiện MyTrait cho một K mỗi loại):

use std::fmt; 

pub trait MyTrait { 
    type K: fmt::Display; 
    fn get_some_k(&self) -> Option<Self::K>; 
} 

impl<S: MyTrait> fmt::Display for S { 
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 
     write!(f, "{}", self.get_some_k().unwrap()) 
    } 
} 

fn main() { } 

Tuy nhiên, khi làm rõ như thế này nó trở nên rõ ràng rằng phương pháp này sẽ không làm việc một trong hai, bởi vì bạn triển khai Display cho tất cả các loại triển khai MyTrait — các loại có thể có triển khai Display của riêng chúng. Này bị cấm, và để bạn có được E0210:

error: type parameter S 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 [E0210]

gói nó trong một cái gì đó giống như bạn đã làm Ugly-là cách duy nhất để cho phép một thực hiện như vậy. Hoặc thực hiện một đặc điểm trong thùng của riêng bạn chứ không phải một cái trong người khác (như Display).

+0

cảm ơn, tôi đã nghĩ đến liên quan loại, nhưng tôi trong trường hợp tôi cần nhiều triển khai cho mỗi loại, nếu không nó sẽ thực hiện công việc (trường hợp sử dụng của tôi không phải là 'Hiển thị'). – cheme

Các vấn đề liên quan