Rust是否有类似于C++的decltype()函数用于获取表达式的类型?

11

我的代码看起来像:

macro_rules! mask {
    ($bitmap: tt, [..$count: tt], for type = $ty: ty) => {
        {
            let bit_count = std::mem::size_of::<$ty>() * 8;
            let dec_bit_count = bit_count - 1;
            $bitmap & [(1 << ($count & dec_bit_count)) - 1, <$ty>::MAX][((($count & !dec_bit_count)) != 0) as usize]
        }
    };
}

fn main() {
    let bitmap: u8 = 0b_1111_1111;
    let masked_bitmap = mask!(bitmap, [..5], for type = u8);
    println!("{:#010b}", masked_bitmap);
}

以上代码将掩盖位图。在上面的示例中,0b_1111_1111[..5]掩盖后将变为0b_0001_1111

我希望我的宏像这样:

macro_rules! mask {
    ($bitmap: tt, [..$count: tt]) => {
        {
            let bit_count = std::mem::size_of::<decltype($bitmap)>() * 8;
            let dec_bit_count = bit_count - 1;
            $bitmap & [(1 << ($count & dec_bit_count)) - 1, <decltype($bitmap)>::MAX][((($count & !dec_bit_count)) != 0) as usize]
        }
    };
}

但是我必须将类型传递给宏才能完成这项任务。是否有类似于C++中可以使用的decltype()的东西?


3
如果你使用mem::size_of_val($bitmap)代替mem::size_of::<$ty>(),并且使用~0代替<$ty>::MAX(因为你的宏只对无符号整数类型有意义),那么你可以删除所有类型实例。 - Jmb
@Jmb,mem::size_of_val()会被任何优化在编译时解释吗? 我以前尝试过你说的方法。 mem::size_of()是一个const函数,因此它会在编译时解决,但我不确定size_of_val - Mihir Luthra
2
根据文档size_of_valsize_of::<T>()相同,除非在编译时无法确定T的大小,在这种情况下它将在运行时计算,而size_of::<T>()则无法编译。 - Jmb
2
而且godbolt显示它在编译时进行了优化。 - Jmb
1个回答

9
不,Rust没有获取任意表达式类型的能力。 typeof是一个保留关键字,可能会在将来允许它:
fn main() {
    let a: i32 = 42;
    let b: typeof(a) = a;
}

error[E0516]: `typeof` is a reserved keyword but unimplemented
 --> src/main.rs:3:12
  |
3 |     let b: typeof(a) = a;
  |            ^^^^^^^^^ reserved keyword

有RFC建议添加此功能。

另请参见:


针对您的具体情况,我建议使用traits代替:
use std::ops::RangeTo;

trait Mask {
    fn mask(self, range: RangeTo<usize>) -> Self;
}

impl Mask for u8 {
    #[inline]
    fn mask(self, range: RangeTo<usize>) -> Self {
        // Feel free to make this your more complicated bitwise logic
        let mut m = 0;
        for _ in 0..range.end {
            m <<= 1;
            m |= 1;
        }
        self & m
    }
}


fn main() {
    let bitmap: u8 = 0b_1111_1111;
    let masked_bitmap = bitmap.mask(..5);
    println!("{:#010b}", masked_bitmap);
}

你可以使用宏来实现特质,如下所示:
macro_rules! impl_mask {
    ($($typ:ty),*) => {
        $(
            impl Mask for $typ {
                #[inline]
                fn mask(self, range: RangeTo<usize>) -> Self {
                    let mut m = 0;
                    for _ in 0..range.end {
                        m <<= 1;
                        m |= 1;
                    }
                    self & m
                }
            }
        )*
    };
}

impl_mask!(u8, u16, u32, u64, u128);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接