Skip to content

Instantly share code, notes, and snippets.

@jFransham
Created February 22, 2016 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jFransham/017bd5bd8f693a04749a to your computer and use it in GitHub Desktop.
Save jFransham/017bd5bd8f693a04749a to your computer and use it in GitHub Desktop.
macro_rules! overloaded {
(
fn $name:ident
$(
($first_name:ident : $first_type:ty) -> $out:ty;
$body:block
)*
) => {
fn $name<T: Inner>(f: T) -> <T as Inner>::Output {
Inner::do_inner(f)
}
trait Inner {
type Output;
fn do_inner(_: Self) -> Self::Output;
}
$(
impl Inner for $first_type {
type Output = $out;
fn do_inner($first_name : Self) -> Self::Output $body
}
)*
};
(
fn $name:ident
$(
(
$first_name:ident : $first_type:ty,
$restn0:ident : $restt0:ty
) -> $out:ty;
$body:block
)*
) => {
fn $name<A, T: Inner<A>>(f: T, p0: A) -> <T as Inner<A>>::Output {
Inner::do_inner(f, p0)
}
trait Inner<A> {
type Output;
fn do_inner(_: Self, _: A) -> Self::Output;
}
$(
impl Inner<$restt0> for $first_type {
type Output = $out;
fn do_inner($first_name : Self, $restn0 : $restt0) -> Self::Output $body
}
)*
};
(
fn $name:ident
$(
(
$first_name:ident : $first_type:ty,
$restn0:ident : $restt0:ty,
$restn1:ident : $restt1:ty
) -> $out:ty;
$body:block
)*
) => {
fn $name<A, B, T: Inner<A, B>>(f: T, p0: A, p1: B) -> <T as Inner<A, B>>::Output {
Inner::do_inner(f, p0, p1)
}
trait Inner<A, B> {
type Output;
fn do_inner(_: Self, _: A, _: B) -> Self::Output;
}
$(
impl Inner<$restt0, $restt1> for $first_type {
type Output = $out;
fn do_inner(
$first_name : Self,
$restn0 : $restt0,
$restn1 : $restt1
) -> Self::Output $body
}
)*
};
(
fn $name:ident
$(
(
$first_name:ident : $first_type:ty,
$restn0:ident : $restt0:ty,
$restn1:ident : $restt1:ty,
$restn2:ident : $restt2:ty
) -> $out:ty;
$body:block
)*
) => {
fn $name<A, B, C, T: Inner<A, B, C>>(f: T, p0: A, p1: B, p2: C) -> <T as Inner<A, B, C>>::Output {
Inner::do_inner(f, p0, p1, p2)
}
trait Inner<A, B, C> {
type Output;
fn do_inner(_: Self, _: A, _: B, _: C) -> Self::Output;
}
$(
impl Inner<$restt0, $restt1, $restt2> for $first_type {
type Output = $out;
fn do_inner(
$first_name : Self,
$restn0 : $restt0,
$restn1 : $restt1,
$restn2 : $restt2
) -> Self::Output $body
}
)*
};
(
fn $name:ident
$(
(
$first_name:ident : $first_type:ty,
$restn0:ident : $restt0:ty,
$restn1:ident : $restt1:ty,
$restn2:ident : $restt2:ty,
$restn3:ident : $restt3:ty
) -> $out:ty;
$body:block
)*
) => {
fn $name<A, B, C, D, T: Inner<A, B, C, D>>(f: T, p0: A, p1: B, p2: C, p3: D) -> <T as Inner<A, B, C, D>>::Output {
Inner::do_inner(f, p0, p1, p2, p3)
}
trait Inner<A, B, C, D> {
type Output;
fn do_inner(_: Self, _: A, _: B, _: C, _: D) -> Self::Output;
}
$(
impl Inner<$restt0, $restt1, $restt2, $restt3> for $first_type {
type Output = $out;
fn do_inner(
$first_name : Self,
$restn0 : $restt0,
$restn1 : $restt1,
$restn2 : $restt2,
$restn3 : $restt3
) -> Self::Output $body
}
)*
};
}
overloaded! {
fn my_thing
(thing: i32, second_thing: u64, third: u8, fourth: u8, fifth: u8) -> i32; {
(thing as u64 * second_thing) as i32
}
(thing: i64, second_thing: u32, third: u8, fourth: u8, fifth: u8) -> i32; {
(thing * second_thing as i64) as i32
}
}
fn main() {
println!("{}", my_thing(3i32, 7u64, 0, 0, 0));
println!("{}", my_thing(3i64, 7u32, 0, 0, 0));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment