rust - 锈中的“可选特征绑定”功能
问题描述
我想为函数提供类似可选特征的东西。如果在哪里T
实现该类型 - 做某事。
fn test<T: Eq + ?Debug>(a:T, b:T){
if a!=b{
println!("Not equal!");
if (T impl Debug){
println!("{:?} != {:?}", a, b);
}
}
}
解决方案
正如@user4815162342 所评论的,使用专业化,这是可能的。
我将提供一种与他们在评论中指定的方法略有不同的方法,以保持与if ... { ... }
原始代码中相同的设置。
这个想法是有一个AsMaybeDebug
具有关联类型的特征Debug
,它总是实现Debug
和一个函数从&Self
to Option<&Self::Debug>
:
trait AsMaybeDebug {
type Debug: Debug;
fn as_maybe_debug(&self) -> Option<&Self::Debug>;
}
在此之后,我们为 all 创建一个默认的 impl T
,调试类型为!
, never 类型,并且总是 return None
。
impl<T> AsMaybeDebug for T {
default type Debug = !;
default fn as_maybe_debug(&self) -> Option<&Self::Debug> {
None
}
}
您可以选择任何始终实现Debug
但仍返回的类型,而不是 never 类型None
。
之后我们专门T: Debug
返回Self
:
impl<T: Debug> AsMaybeDebug for T {
type Debug = Self;
fn as_maybe_debug(&self) -> Option<&Self::Debug> {
Some(self)
}
}
最后,test
我们只需调用as_maybe_debug
并检查是否T: Debug
fn test<T: Eq>(a: T, b: T){
if a != b {
println!("Not equal!");
if let (Some(a), Some(b)) = (a.as_maybe_debug(), b.as_maybe_debug()) {
println!("{:?} != {:?}", a, b);
}
}
}
您可以在操场上检查它是否可以工作,并且生成的程序集test_non_debug
没有任何调试调用,只有对std::io::_print
.
不幸的是,无法在after call中检索原始文件a
或b
内部文件。if
as_maybe_debug
这是由于<Self as AsMaybeDebug>::Debug
不能转换回Self
. 这可以修复,但不容易,因为它需要标准库的更新。
要求AsMaybeDebug::Debug: AsRef<Self>
不起作用有两个原因:
-
- 还没有
impl<T> AsRef<T> for T
,我想这是因为专业化仍然不完整。
- 还没有
-
- 还没有
impl<T> AsRef<T> for !
。不确定是否可以通过专业化来制作这个 impl,但它是必需的。
- 还没有
此外,虽然specialization
可能不健全,但我相信 trait 及其 impls 不能用于不健全,你需要一个特定的设置才能从中产生不健全,这是缺乏的。
推荐阅读
- r - 将重复的列组合成一列数据框 r
- import - Rust:根目录中没有“模块”
- docker - 加快Docker内部时间的方法?
- python - Django:如何使用 MySQL 数据库检索最新的、唯一命名的记录的查询集
- html - 如何将html中的文本居中?
- reactjs - 在 React 应用程序中从服务器而不是客户端进行 ajax 调用?
- time - 你好,谁能帮我用 Pine Script 中的时间函数?
- youtube - 很难构建 youtube/cobalt,当我构建它时,有很多问题
- get - 无法获取网页内容
- python - 在新的文本文件中列出文本文件名称以读取链接。在打印命令中获得期望结果,但尝试将其保存在文件或列表中