User avatar
MarkAssPandi @MarkAssPandi@shrimpnet.gej.pet
1mo
@famfo I recently was so bored that I made something ala function overloading using Any
Yes I accept death threats in my dms
use std::any::{Any, TypeId};
use std::collections::HashMap;

struct Overloaded {
    map: HashMap<TypeId, Box<dyn Fn(Box<dyn Any>) -> Box<dyn Any>>>,
}

impl Overloaded {
    fn new() -> Self {
        Self {
            map: HashMap::new(),
        }
    }

    fn register<F, Params, Ret>(&mut self, f: F)
    where
        F: Fn(Params) -> Ret + 'static,
        Params: 'static,
        Ret: 'static,
    {
        self.map.insert(
            TypeId::of::<Params>(),
            Box::new(move |p: Box<dyn Any>| {
                let params = *p.downcast::<Params>().expect("Invalid params at reg");
                Box::new(f(params)) as Box<dyn Any>
            }),
        );
    }

    fn call<Params, R>(&self, params: Params) -> R
    where
        Params: 'static,
        R: 'static,
    {
        let f = self
            .map
            .get(&TypeId::of::<Params>())
            .expect("Does not exist");
        *f(Box::new(params))
            .downcast::<R>()
            .expect("Failed to downcast")
    }
}

fn main() {
    let mut sum = Overloaded::new();
    sum.register(|(s,)| sum1(s));
    sum.register(|(s1, s2)| sum2(s1, s2));
    sum.register(|(s1, s2, s3)| sum3(s1, s2, s3));
    sum.register(|(s1, s2, s3, s4)| sum4(s1, s2, s3, s4));
    sum.register(|(s1, s2, s3, s4, s5)| sum5(s1, s2, s3, s4, s5));
    sum.register(|(s1, s2, s3, s4, s5, s6)| sum6(s1, s2, s3, s4, s5, s6));
    sum.register(|(s1, s2, s3, s4, s5, s6, s7)| sum7(s1, s2, s3, s4, s5, s6, s7));
    sum.register(|(s1, s2, s3, s4, s5, s6, s7, s8)| sum8(s1, s2, s3, s4, s5, s6, s7, s8));
    sum.register(|(s1, s2, s3, s4, s5, s6, s7, s8, s9)| sum9(s1, s2, s3, s4, s5, s6, s7, s8, s9));

    println!("2 + 2 = {}", sum.call::<_, usize>((2usize, 2usize)));
    println!("3+5+6 = {}", sum.call::<_, usize>((3usize, 5usize, 6usize)));
}