在宏中引用通用类型的结构

Refer to generic type of struct in macro

我需要在宏中使用结构的泛型类型的属性。

如果我想为泛型结构实现一个返回其泛型类型的最小值的方法,那么一个稍微做作但最小的例子就是。

struct Barn<T> {
    hay: T
}

macro_rules! impl_min_hay{
    ($barntype:ident) => {
        impl $barntype {
            fn min_hay(&self) -> ????T {
                ????T::MIN
            }
        }
    }
}

type SmallBarn = Barn<i8>;
type BigBarn = Barn<i64>;

impl_min_hay!(SmallBarn);
impl_min_hay!(BigBarn);

fn main() {
    
    let barn = SmallBarn { hay: 5 };
    println!("{}", barn.min_hay());
}

我如何从 SmallBarn 解析为通用类型并因此获得 MIN 属性?

我试图解决的实际问题是对 this macro 的更改。该宏应用于 BooleanChunked 等,其定义为: pub type BooleanChunked = ChunkedArray<BooleanType>

而且我需要使用 BooleanType 的属性

我能想到的唯一通用解决方案是定义一个允许您获取类型参数的特征(语法为 <Type as Trait>::AssociatedType):

trait HasHayType {
    type HayType;
}
impl<T> HasHayType for Barn<T> {
    type HayType = T;
}

macro_rules! impl_min_hay{
    ($barntype:ident) => {
        impl $barntype {
            fn min_hay(&self) -> <$barntype as HasHayType>::HayType {
                <$barntype as HasHayType>::HayType::MIN
            }
        }
    }
}

Here's the complete program on play.rust-lang.org.

就是说,一旦你有了一个特征,你就不需要宏了——你可以只在特征上实现 min_hay(这个例子使用了广泛使用的 num-traits crate ,因为这种方法需要“具有最小值的事物”的特征):

use num_traits::Bounded;
trait HasHayType {
    type HayType: Bounded;
    fn min_hay(&self) -> Self::HayType;
}
impl<T: Bounded> HasHayType for Barn<T> {
    type HayType = T;
    fn min_hay(&self) -> T {
        T::min_value()
    }
}

And here's what that looks like as a complete program.

(当然,一旦你也这样做了,你也不需要单独的特征:你可以将 HasHayType 的定义内联到 Barn,使用 where 子句,如果你希望能够处理 Barns 与非数字干草类型除了那些你会使用宏的。不过,据推测,你的实际情况更复杂比你用于问题的简化示例,所以我给出了更复杂的版本,以防简化版本不起作用。)

附带说明一下,min_hay 这里实际上不需要 &self 参数;你可以移除它,以便能够在不需要谷仓的情况下学习最少数量的干草。