简体   繁体   中英

How can I implement the From trait for all types implementing a trait but use a specific implementation for certain types?

I am implementing the std::convert::From trait for a struct containing a Cow<str> . Is there a way to use the same implementation for all different kinds of integers ( u8 , u16 , u32 , usize and so on)?

use std::borrow::Cow;

pub struct Luhn<'a> {
    code: Cow<'a, str>,
}

I can easily implement code for all integers using a trait bound on the ToString trait, but then I cannot use a specific implementation for str and String - this way the benefits of Cow cannot be exploited. When I write specific implementations for str and String , I get a compile error:

 error[E0119]: conflicting implementations of trait `std::convert::From<&str>` for type `Luhn<'_>`: --> src/lib.rs:23:1 | 7 | impl<'a> From<&'a str> for Luhn<'a> { | ----------------------------------- first implementation here ... 23 | impl<'a, T: ToString> From<T> for Luhn<'a> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Luhn<'_>` 

I understand that this is due to the fact that Rust does not offer function overloading. How could this be solved in an elegant way?

impl<'a> From<&'a str> for Luhn<'a> {
    fn from(input: &'a str) -> Self {
        Luhn {
            code: Cow::Borrowed(input),
        }
    }
}

impl<'a> From<String> for Luhn<'a> {
    fn from(input: String) -> Self {
        Luhn {
            code: Cow::Owned(input),
        }
    }
}

impl<'a, T: ToString> From<T> for Luhn<'a> {
    fn from(input: T) -> Self {
        Luhn {
            code: Cow::Owned(input.to_string()),
        }
    }
}

Since &str and String both implement ToString , you can use the unstable specialization feature:

#![feature(specialization)]

use std::borrow::Cow;

pub struct Luhn<'a> {
    code: Cow<'a, str>,
}

impl<'a, T: ToString> From<T> for Luhn<'a> {
    default fn from(input: T) -> Self {
//  ^^^^^^^
        Luhn {
            code: Cow::Owned(input.to_string()),
        }
    }
}

impl<'a> From<&'a str> for Luhn<'a> {
    fn from(input: &'a str) -> Self {
        Luhn {
            code: Cow::Borrowed(input),
        }
    }
}

impl<'a> From<String> for Luhn<'a> {
    fn from(input: String) -> Self {
        Luhn {
            code: Cow::Owned(input),
        }
    }
}

That being said, you cannot implement Display for Luhn because you'd run into How is there a conflicting implementation of `From` when using a generic type?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM