简体   繁体   English

通用超特征/需要一揽子实现

[英]Generic supertrait / requiring blanket impl

Currently, I have a trait like this:目前,我有这样的特质:

trait Trait
where
    Self: Sized,
{
    fn try_form_u8(num: u8) -> Option<Self>;
    fn try_from_str<T: AsRef<str>>(s: &T) -> Option<Self>;
    // ...
}

Optimally, I want to define it like simliar to this, in order to not have try_from_* methods outside of a TryFrom implementation:最佳情况下,我想像这样定义它,以便在TryFrom实现之外没有try_from_*方法:

trait Trait: for<T: AsRef<str>> TryFrom<u8> + TryFrom<T>
where
    Self: Sized
{
    // ...
}

I couldn't find a way to accomplish that and finally came across this thread: Can a trait have a supertrait that is parameterized by a generic?我找不到实现这一目标的方法,最后遇到了这个线程: 特征可以有一个由泛型参数化的超特征吗?

I wonder how to continue from here.我想知道如何从这里继续。 Should I use the unconventional try_from_str method or is there a better way to express what is needed here?我应该使用非常规的try_from_str方法还是有更好的方法来表达这里需要的内容?

Note that in my original code I have Path instead of str , which could eliminate some special solutions, but I would still like to know them if there are any nice solution!请注意,在我的原始代码中,我使用Path而不是str ,这可以消除一些特殊的解决方案,但如果有任何好的解决方案,我仍然想知道它们!

If a type implements TryFrom<&str> , it is trivial to create it from a String or Rc<str> or anything else that is AsRef<str> .如果一个类型实现了TryFrom<&str> ,那么从StringRc<str>或任何其他AsRef<str>创建它是微不足道的。 So let's start with that:让我们从这个开始:

trait Trait: TryFrom<u8> + for<'a> TryFrom<&'a str> {}

It's easy to use this with other types simply by calling .as_ref() , but if you still want the generic version, you can provide a default implementation:只需调用.as_ref()即可轻松将其与其他类型一起使用,但如果您仍然需要通用版本,则可以提供默认实现:

trait Trait: TryFrom<u8> + for<'a> TryFrom<&'a str> {
    fn try_from_str<S: AsRef<str>>(arg: &S) -> Result<Self, <Self as TryFrom<&str>>::Error> {
        arg.as_ref().try_into()
    }
}

This way, implementors of Trait don't have to write anything special, but users still have the convenient try_from_str function.这样, Trait实现者不必编写任何特殊的东西,但用户仍然可以使用方便的try_from_str函数。

Path version Path版本

trait Trait: TryFrom<u8> + for<'a> TryFrom<&'a Path> {
    fn try_from_path<P: AsRef<Path>>(arg: &P) -> Result<Self, <Self as TryFrom<&Path>>::Error> {
        arg.as_ref().try_into()
    }
}

str version str版本

For str specifically, you might want to use the standard library trait FromStr instead of TryFrom , which is more specialized to this use case, enables str::parse and does not require a higher-ranked trait bound:特别是对于str ,您可能希望使用标准库特征FromStr而不是TryFrom ,后者更专门用于此用例,启用str::parse并且不需要更高排名的特征边界:

trait Trait: TryFrom<u8> + FromStr {
    fn try_from_str<S: AsRef<str>>(arg: &S) -> Result<Self, <Self as FromStr>::Err> {
        arg.as_ref().parse()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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