Function comparing 2 variables of any type

Viewed 149

A tricky problem. I have to implement a function fn eq( a, b ) comparing a and b. The function should return false if either types of variables are different or variables have different values. The function should return true if both type and value are the same.

A possible solution is to use dyn Any as Netwave advised. But such a solution has limited application because it restricts arguments of eq with static constraint. Maybe it is possible to come up with a more practical implementation? Playground of such a solution.

1 Answers

Well, playing with Any is not so difficult to implement something:

use std::any::Any;
use std::any::TypeId;

fn eq<T: Any + Eq, Q: Any + Eq>(a: T, b: Q) -> bool {
    if TypeId::of::<T>() == TypeId::of::<Q>() {
        let b_as_t = &b as &dyn Any;
        // safe to unwrap, we matched the type already
        &a == b_as_t.downcast_ref::<T>().unwrap()
    } else {
        false    
    }
}

fn main() {
    assert!(!eq("foo", 1));
    assert!(eq(1, 1));
    assert!(eq(&1, &1));
    assert!(!eq(&'a', &1));

}

Playground

As per the comments, it may be possible to have another version that works over references directly:

use std::any::Any;
use std::any::TypeId;

fn eq<T: Any + Eq, Q: Any + Eq>(a: &T, b: &Q) -> bool {
    if TypeId::of::<T>() == TypeId::of::<Q>() {
        let b_as_t = b as &dyn Any;
        // safe to unwrap, we matched the type already
        *a == *b_as_t.downcast_ref::<T>().unwrap()
    } else {
        false    
    }
}

fn main() {
    assert!(!eq(&"foo", &1));
    assert!(eq(&1, &1));
    assert!(eq(&1, &1));
    assert!(!eq(&'a', &1));
    let s1 = "foo".to_owned();
    let s2 = "foo".to_owned();
    assert!(eq(&s1, &s2));
}

Playground

Related