我想匹配,例如一个ident
的类型来实现某个特征,我该怎么做?
这里是(不完整)代码的基本思想:
macro_rules! has_trait {
($ ($t : ty), ($x : ident),) => {
}
}
fn trait_test() {
let a = vec![1, 2, 3];
let b = 42;
let a_iteratable = has_trait!(IntoIterator, a);
let b_iteratable = has_trait!(IntoIterator, b);
println!("{:?} iterable? {}", a, a_iteratable);
println!("{:?} iterable? {}", b, b_iteratable);
}
我无法理解如何说“任何有特质Foo
的类型”。
我看到了如何解决问题的两个选项:
$t
,只需在匹配时返回true,否则(其他方法如何?)false。$t
是否由$x
类型实现。我看不懂两种选择中的任何一种。
甚至可以这样做吗?
答案 0 :(得分:4)
我担心这里存在一个严重的误解,即宏可以做什么,不能做什么。
在Rust中,宏作用于AST,是Abstract 语法树的缩写。这意味着它只能访问语法信息。
这意味着宏所做的任何事情,你也可以没有宏。宏是只是语法糖,以避免一遍又一遍地编写样板。
相反,如果你不能在没有宏的情况下做某事,你也不能用宏来做。
我不能立即清楚这些信息是否可用(证明负面信息总是如此困难),但可以肯定的是,宏的使用对此可用性没有影响。
答案 1 :(得分:2)
正如其他答案已经明确表示的那样,宏无法做到。事实上,在当前(稳定)Rust中,就是这样。但是,如果您愿意每晚使用或等到专业化稳定,您可以编写并实施一个特征来区分,例如。
#[feature(specialization)] // nightly only for now
trait HasMyTrait {
fn has_trait() -> bool;
}
impl<T> HasMyTrait for T {
default fn has_trait() -> bool { false }
}
impl<T: MyTrait> HasMyTrait for T {
fn has_trait() -> bool { true }
}
这只是一个简单的例子,但是如果所讨论的类型是否实现了特征,你可以根据你想要的任何功能切换出多个实现。
此代码从2016-06-02或更新版本每晚需要Rust 1.11.0。
答案 2 :(得分:1)
你基本上想要的是静态(或编译时)反射: 根据类型系统在编译时分配值,以便在运行时使用。 这在例如D或甚至C ++中是可能的,但在Rust中不可能。
Rust不允许模板特化或编译时值作为通用参数,也不具有像D这样的静态反射功能。