Skip to content

Instantly share code, notes, and snippets.

@Vonr
Last active August 15, 2023 16:22
Show Gist options
  • Select an option

  • Save Vonr/16a9f271e7d499ef3f6b1509e8d5141f to your computer and use it in GitHub Desktop.

Select an option

Save Vonr/16a9f271e7d499ef3f6b1509e8d5141f to your computer and use it in GitHub Desktop.
Function Overloading Macro for Nightly Rust (180dffba1)
#![feature(unboxed_closures)]
#![feature(fn_traits)]
/// Please do not actually use this.
/// This was only made as a proof-of-concept.
macro_rules! idents_to_tuple {
() => {
()
};
($name:ident) => {
($name,)
};
($($name:ident),+$(,)?) => {
($($name),+)
};
}
macro_rules! types_to_tuple {
() => {
()
};
($type:ty) => {
($type,)
};
($($type:ty),+$(,)?) => {
($($type),+)
};
}
macro_rules! type_or_unit {
() => {
()
};
($type:ty) => {
$type
};
}
macro_rules! overloading {
($type:tt {
$(
($($name:ident: $arg:ty),*) $(-> $ret:ty)? {
$body:expr
}
)*
}) => {
#[allow(non_camel_case_types)]
struct $type;
$(
impl FnOnce<types_to_tuple!($($arg),*)> for $type
where
$type: std::ops::Fn<types_to_tuple!($($arg),*)>,
{
type Output = type_or_unit!($($ret)?);
extern "rust-call" fn call_once(self, args: types_to_tuple!($($arg),*)) -> Self::Output {
self.call(args)
}
}
impl FnMut<types_to_tuple!($($arg),*)> for $type
where
$type: std::ops::Fn<types_to_tuple!($($arg),*)>,
{
extern "rust-call" fn call_mut(&mut self, args: types_to_tuple!($($arg),*)) -> Self::Output {
self.call(args)
}
}
impl Fn<types_to_tuple!($($arg),*)> for $type {
extern "rust-call" fn call(&self, idents_to_tuple!($($name),*): types_to_tuple!($($arg),*)) -> Self::Output {
$body
}
}
)*
};
}
overloading!(cursed {
(name: String) {{
println!("{name}")
}}
(num: usize) -> usize {{
println!("{num}");
num + 1
}}
() {{
println!("No arguments?");
}}
});
fn main() {
cursed("test".to_string());
println!("{}", cursed(1337usize));
cursed();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment