如何在Rust中测试类型相等性?

9

我需要测试两种类型是否相等在const fn里。比较TypeId是行不通的:

#![feature(const_if_match)]
#![feature(const_fn)]
#![feature(const_type_id)]

const fn t<T1: 'static, T2: 'static>() -> bool{
    std::any::TypeId::of::<T1>() == std::any::TypeId::of::<T2>()
}

错误:

error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 --> src/lib.rs:5:8
  |
5 |     std::any::TypeId::of::<T1>()==std::any::TypeId::of::<T2>()
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

在 Rust 中,像 C++ 中的模板特化并不起作用,因为 Rust 没有 "模板特化"。那么,在 Rust 中有没有任何方法可以测试类型相等性呢?

2个回答

13

如果您正在使用 Rust nightly(似乎是这样),您可以使用不稳定的specialization功能和一些辅助特性来完成此操作:

#![feature(specialization)]

/// Are `T` and `U` are the same type?
pub const fn type_eq<T: ?Sized, U: ?Sized>() -> bool {
    // Helper trait. `VALUE` is false, except for the specialization of the
    // case where `T == U`.
    trait TypeEq<U: ?Sized> {
        const VALUE: bool;
    }

    // Default implementation.
    impl<T: ?Sized, U: ?Sized> TypeEq<U> for T {
        default const VALUE: bool = false;
    }

    // Specialization for `T == U`.
    impl<T: ?Sized> TypeEq<T> for T {
        const VALUE: bool = true;
    }

    <T as TypeEq<U>>::VALUE
}

在游乐场中的示例


类型需要是'static - undefined

0
另一个稳定的解决方案是滥用auto-deref specialization
macro_rules! eq_type {
    ($a:ty, $b:ty) => {
        {
            use $crate::EqType;
            (&&&$crate::Wrap::<($a, $b)>(::core::marker::PhantomData)).eq_type()
        }
    }
}

struct Wrap<T>(::core::marker::PhantomData<fn(T) -> T>);

trait EqType {
    fn eq_type(&self) -> bool;
}

impl<A> EqType for &&Wrap<(A, A)> {
    fn eq_type(&self) -> bool {
        true
    }
}

impl<A, B> EqType for &Wrap<(A, B)> {
    fn eq_type(&self) -> bool {
        false
    }
}

mod tests {
    #[test]
    fn as_eq() {
        assert!(eq_type!(i32, i32));
    }
    
    #[test]
    fn as_ne() {
        assert!(!eq_type!(i32, u32));
    }
}

这将无法与通用功能一起使用。 - undefined

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