Is there a simple way to overload functions?

Yes, this is good, but one thing to note is that if I should ask for a impl FnMut(i32, i32) -> i32 I'd be out of luck because you haven't implemented those. overloadable will already do this for you, so you needn't worry about it.

But in the case you want your functions to get interesting, you could do the following:

overloadable::overloadable! {
    pub get_max as
    fn<T: PartialOrd>(x: T, y: T) -> T {
        if x > y { x } else { y }
    },
    fn<T: PartialOrd>(x: T, y: T, z: T) -> T {
        if x > y && x > z { x } else if y > z && y > x { y } else { z }
    },
    fn<T: PartialOrd>([x, y, z, w]: [T; 4]) -> T {
        if x > y && x > z && x > w {
            x
        } else if y > x && y > z && y > w {
            y
        } else if z > x && z > y && z > w {
            z
        } else {
            w
        }
    }
}
Which would expand to the following three generic trait implementations:
pub struct get_max;
impl<T: PartialOrd> Fn<(T, T)> for get_max {
    extern "rust-call" fn call(&self, (x, y): (T, T)) -> Self::Output {
        {
            if x > y {
                x
            } else {
                y
            }
        }
    }
}
impl<T: PartialOrd> FnOnce<(T, T)> for get_max{
    type Output = T;
    extern "rust-call" fn call_once(self, x: (T, T)) -> Self::Output {
        self.call(x)
    }
}
impl<T: PartialOrd> FnMut<(T, T)> for get_max{
    extern "rust-call" fn call_mut(&mut self, x: (T, T)) -> Self::Output {
        self.call(x)
    }
}
impl<T: PartialOrd> Fn<(T, T, T)> for get_max{
    extern "rust-call" fn call(&self, (x, y, z): (T, T, T)) -> Self::Output {
        {
            if x > y && x > z {
                x
            } else if y > z && y > x {
                y
            } else {
                z
            }
        }
    }
}
impl<T: PartialOrd> FnOnce<(T, T, T)> for get_max {
    type Output = T;
    extern "rust-call" fn call_once(self, x: (T, T, T)) -> Self::Output {
        self.call(x)
    }
}
impl<T: PartialOrd> FnMut<(T, T, T)> for get_max {
    extern "rust-call" fn call_mut(&mut self, x: (T, T, T)) -> Self::Output {
        self.call(x)
    }
}
impl<T: PartialOrd> Fn<([T; 4],)> for get_max {
    extern "rust-call" fn call(&self, ([x, y, z, w],): ([T; 4],)) -> Self::Output {
        {
            if x > y && x > z && x > w {
                x
            } else if y > x && y > z && y > w {
                y
            } else if z > x && z > y && z > w {
                z
            } else {
                w
            }
        }
    }
}
impl<T: PartialOrd> FnOnce<([T; 4],)> for get_max {
    type Output = T;
    extern "rust-call" fn call_once(self, x: ([T; 4],)) -> Self::Output {
        self.call(x)
    }
}
impl<T: PartialOrd> FnMut<([T; 4],)> for get_max {
    extern "rust-call" fn call_mut(&mut self, x: ([T; 4],)) -> Self::Output {
        self.call(x)
    }
}

You can get very creative with these implementations, with the only things I can think of being different than standard functions being the following:

  • Specialization wouldn't work
  • impl Trait parameters and return types wouldn't work either.
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.