如何在struct方法中为self类型添加别名?

时间:2015-05-24 15:02:42

标签: rust

如果我有一个小结构Test

struct Test<T> { a: T }

我希望,Test的方法可以引用其完整类型:

impl<T> Test<T> {
    fn new(a: T) -> Test<T> {
        type X = Test::<T>;
        println!("{}", std::intrinsics::type_id::<X>());
        Test { a: a }
    }
}

fails带有预期标识,找到< ,以下内容也失败了:

  • type X = Test;错误的类型参数数量:预期为1,找到0 [E0243]
  • type X = Test<T>;不能使用外部函数的类型参数;尝试使用本地类型参数,并使用注释使用未声明的类型名称T

实际上,前两者被拒绝是有道理的;然而后者则更加神秘。

这是在尝试实施offset_of!宏时出现的:offset_of($T:ty, $field:ident);该宏工作得相当好,但ty不接受Test<T>(但接受无参数别名)。

有没有办法:

  • 制作self类型的别名,即使在泛型中也是如此?
  • 或者,可以使宏接受Test<T>作为“类型”参数?

注意:如果可能的话,我更喜欢前者的解决方案,因为别名非常方便。

供参考,这是我制作的offset_of宏:

macro_rules! offset_of(
    ($T:ty, $field:ident) => {
        unsafe {
            let exemplar: $T = std::mem::uninitialized();
            let base: *const u8 = std::mem::transmute(&exemplar);
            let attr: *const u8 = std::mem::transmute(&exemplar.$field);
            std::mem::forget(exemplar);
            (attr as isize) - (base as isize)
        }
    }
);

1 个答案:

答案 0 :(得分:2)

我可能误解了你,但已经有了自我类型的别名 - Self

#![feature(core)]

struct Test<T> { a: T }

impl<T> Test<T> {
    fn new(a: T) -> Test<T>
        where T: 'static
    {
        println!("{}", unsafe { std::intrinsics::type_id::<Self>() });
        Test { a: a }
    }
}

fn main() {}

我必须添加功能门,使T 'static满足type_id,并添加不安全的阻止。我希望这一切看起来都不可疑。这似乎与您的别名一起使用:

macro_rules! offset_of(
    ($T:ty, $field:ident) => {
        unsafe {
            let exemplar: $T = std::mem::uninitialized();
            let base: *const u8 = std::mem::transmute(&exemplar);
            let attr: *const u8 = std::mem::transmute(&exemplar.$field);
            (attr as isize) - (base as isize)
        }
    }
);

struct Test<T> { a: T, b: T, c: T }

impl<T> Test<T> {
    fn new(a: T) -> Test<T>
        where T: Copy
    {
        println!("{}", offset_of!(Self, a));
        println!("{}", offset_of!(Self, b));
        println!("{}", offset_of!(Self, c));
        Test { a: a, b: a, c: a }
    }
}

fn main() {
    Test::new(1u16);
}