如何检查结构是否实现某些特征并计算布尔结果。
例如:
struct Foo;
struct Bar;
trait Qux {}
impl Qux for Foo {}
const fn is_qux<T>() -> bool { ... }
assert!(is_qux::<Foo>());
assert_ne!(is_qux::<Bar>());
Run Code Online (Sandbox Code Playgroud)
我知道三种实现方法。没有一个是完美的。
最好的方法是使用专业化:
#![feature(specialization)]
const fn is_qux<T: ?Sized>() -> bool {
trait IsQuxTest {
const IS_QUX: bool;
}
impl<T: ?Sized> IsQuxTest for T {
default const IS_QUX: bool = false;
}
impl<T: ?Sized + Qux> IsQuxTest for T {
const IS_QUX: bool = true;
}
<T as IsQuxTest>::IS_QUX
}
Run Code Online (Sandbox Code Playgroud)
游乐场。
然而,该解决方案存在多个问题:
impl. 例如:fn foo<'a>(v: &'a String) {
struct Foo<'a>(&'a String);
impl Qux for Foo<'static> {}
println!("{}", is_qux::<Foo<'a>>());
}
fn main() {
let v = String::new();
static S: String = String::new();
print!("is_qux::<Foo<'static>>() = "); foo(&S);
print!("is_qux::<Foo<'non_static>>() = "); foo(&v);
}
Run Code Online (Sandbox Code Playgroud)
游乐场。
输出:
is_qux::<Foo<'static>>() = true
is_qux::<Foo<'non_static>>() = true // ???
Run Code Online (Sandbox Code Playgroud)
下一个解决方案是使用deref 专业化或基于在特征方法之前选择固有方法的事实进行专业化(如果可能的话),如 @Aiden4 所建议的。不幸的是,正如前面所说,这不适用于泛型。
最后一种方法是最有趣的:它利用标准库中现有的专业化。例如,数组实现了Clone,但如果元素类型实现了Copy,它们会使用按位复制来克隆自身(因为这样更快)。然而,Clone并不要求做同样的事情Copy(尽管强烈建议这样做)——这一事实使得这种行为可以观察到,并允许我们使用以下巧妙的技巧(这个想法来自这里):
is_qux::<Foo<'static>>() = true
is_qux::<Foo<'non_static>>() = true // ???
Run Code Online (Sandbox Code Playgroud)
游乐场。
它可以调整为 std 中的许多专业化,例如这个。
该解决方案在幕后使用专业化,因此专业化的警告 #3 仍然适用。然而,它使用现有的专业化,因此可以在稳定状态下使用 - 而且,它因此也是完全健全的。然而,它还有另一个警告:我不确定 Rust 的稳定性保证是否适用于这种情况,因此它将来可能会崩溃。除此之外,这个解决方案还不是——尽管如果将来const相关功能得到统一,它可能会成为。const
| 归档时间: |
|
| 查看次数: |
3333 次 |
| 最近记录: |