如何在Rust宏中匹配表达式的类型? [英] How do I match the type of an expression in a Rust macro?

查看:352
本文介绍了如何在Rust宏中匹配表达式的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这只是伪代码:

macro_rules! attribute {
    $e: expr<f32> => { /* magical float stuff */ };
    $e: expr<i64> => { /* mystical int stuff */ };
};

我希望有一个不同的扩展宏,具体取决于我传递给宏的类型.

I would like to have a differently expanded macro depending on the type that I passed to the macro.

这就是它在C ++中的工作方式

This is how it would work in C++

template <typename T>
struct Attribute{ void operator(T)() {} };

template <>
struct Attribute<float> {
    void operator(float)(float) { /* magical float stuff */ }
};

template <>
struct Attribute<long> {
    void operator()(long) { /* mystical int stuff */ }
}

推荐答案

Rust宏无法做到这一点.宏在语法级别而不是语义级别上运行.这意味着尽管编译器知道它具有一个表达式(语法),但在扩展宏的那一刻它不知道该表达式的值的类型(语义).

Rust macros aren't able to do that. Macros operate at the syntactic level, not at the semantic level. That means that although the compiler knows it has an expression (syntax), it doesn't know what the type of the expression's value (semantic) is at the moment the macro is expanded.

一种解决方法是将期望的类型传递给宏:

A workaround would be to pass the expected type to the macro:

macro_rules! attribute {
    ($e:expr, f32) => { /* magical float stuff */ };
    ($e:expr, i64) => { /* mystical int stuff */ };
}

fn main() {
    attribute!(2 + 2, i64);
}

或更简单地说,定义多个宏.

Or, more simply, define multiple macros.

如果要基于表达式的类型进行静态(编译时)分派,则可以使用特征.使用必要的方法定义特征,然后为所需的类型实现特征.如果impl块与特征定义在同一个箱中,则可以为任何类型(包括原始库和其他库的类型)实现特征.

If you want to do static (compile-time) dispatch based on the type of an expression, you can use traits. Define a trait with the necessary methods, then implement the trait for the types you need. You can implement a trait for any type (including primitives and types from other libraries) if the impl block is in the same crate as the trait definition.

trait Attribute {
    fn process(&self);
}

impl Attribute for f32 {
    fn process(&self) { /* TODO */ }
}

impl Attribute for i64 {
    fn process(&self) { /* TODO */ }
}

macro_rules! attribute {
    ($e:expr) => { Attribute::process(&$e) };
}

fn main() {
    attribute!(2 + 2);
}

注意:您也可以在宏的主体中编写$e.process(),但是宏可能会调用不相关的process方法.

Note: You could also write $e.process() in the macro's body, but then the macro might call an unrelated process method.

这篇关于如何在Rust宏中匹配表达式的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆