#overloading #function #no-std #overloadable

nightly no-std overloadf

解锁Rust函数重载

9个版本

0.1.8 2023年5月12日
0.1.7 2020年5月29日

#2#overload

Download history 3/week @ 2024-03-13 20/week @ 2024-03-27 38/week @ 2024-04-03

54 每月下载量

MIT 许可证

24KB
146 代码行数(不含注释)

Crates.io License Build Status

overloadf 版本 - 0.1.7

Overloadf

** 让Rust中的函数重载成为可能 **

只需在函数顶部添加一个属性,就可以使用不同的参数重载函数。当前实现仍存在一些缺陷和待办事项,所以请自行承担风险。

这个库基于一些不稳定的功能。要使用此库,请将以下行放在crate根目录和测试文件的开头:

#![feature(fn_traits, unboxed_closures)]

目前无法实现一些功能:

  • 不安全函数重载
  • const函数重载
  • 函数重载的不同隐私设置(将采用第一个函数的隐私设置并应用于所有)
  • 特性和实现中的函数重载(针对有限情况)

示例

简单的示例

#![feature(fn_traits, unboxed_closures)]

use overloadf::*;

#[overload]
pub fn xdd() -> i32 {
    5_i32
}

#[overload]
pub fn xdd(number: i32) -> i32 {
    number * 3
}

#[overload]
pub fn xdd(number: u8) {
    println!("{}", number);
}

#[overload]
pub unsafe fn xdd(number: &u64) -> u64 {
    let n = number as *const u64;
    *n * 4
}

assert_eq!(xdd(3_i32), 9_i32);
let c: &u64 = &6_u64;
assert_eq!(xdd(c), 24_u64); // unsafe function is not supported.
assert_eq!(xdd(), 5_i32);

泛型和自定义类型

#![feature(fn_traits, unboxed_closures)]

use overloadf::*;
use std::ops::MulAssign;
use std::fmt::Debug;
#[overload]
pub fn xdd<T: Copy + Debug + MulAssign<i32>>(mut number: T) -> T
where
    T: PartialEq,
{
    println!("number {:?}", number);
    number *= 3_i32;
    number
}

struct ABC;
impl Debug for ABC {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "xdddd")
    }
}

#[overload]
pub fn xdd(number: ABC) -> () {
    println!("number {:?}", number);
}
let aa = 123;
assert_eq!(xdd(aa), 369);
assert_eq!(xdd(ABC), ());

异步/await

#![feature(fn_traits, unboxed_closures)]
use overloadf::*;

#[overload]
pub async fn xdd(number: i32) -> i32 {
    number + 3
}
#[overload]
pub async fn xdd(number: i64) -> i64 {
    number + 4
}
assert_eq!(futures::executor::block_on(xdd(3_i32)), 6);
assert_eq!(futures::executor::block_on(xdd(3_i64)), 7);

如果泛型与实现类型的定义重叠,则可能会发生类型冲突

#![feature(fn_traits, unboxed_closures)]

use overloadf::*;
use std::ops::Mul;
use std::fmt::Debug;
#[overload]
pub fn xdd(number: i32) -> i32 {
    number * 2
}
#[overload]
pub fn xdd<T: Copy + Debug + Mul<i32>>(number: T) -> T {
    number * 3_i32
}

对于特性和方法(注意,用于重载的特性和必须继承Sized)

#![feature(fn_traits, unboxed_closures)]
use overloadf::*;
#[overload]
trait Xdd: Sized {
    fn new(input: i32) -> Self;
    fn new(input :u32) -> Self;
}
struct Haha {
    a: u32,
    b: i32,
}
#[overload]
impl Xdd for Haha {
    fn new(b: i32) -> Self {
        Self {
            a: 1,
            b,
        }
    }
    fn new(a: u32) -> Self {
        Self {
            a,
            b: 2,
        }
    }
}
let haha = Haha::new(12_i32);
assert_eq!(haha.a, 1_u32);
assert_eq!(haha.b, 12_i32);
let haha = Haha::new(9_u32);
assert_eq!(haha.a, 9_u32);
assert_eq!(haha.b, 2_i32);

动态特性和对象实现

#![feature(fn_traits, unboxed_closures)]
use overloadf::*;
trait Xdd: 'static {}

#[overload]
impl dyn Xdd {
    fn abc(&self, c: i32) -> i32 {
        c
    }
    fn abc(&self, c: u32) -> u32 {
        c
    }
}

impl<T: 'static + ?Sized> Xdd for T {}
let obj = (&3_i32 as &(dyn Xdd));
// here we lost the syntax sugar of calling obj.abc(c) directly
assert_eq!(Xdd::abc(obj, 3_i32), 3_i32);
assert_eq!(Xdd::abc(obj, 3_u32), 3_u32);

泛型特性和

#![feature(fn_traits, unboxed_closures)]
use overloadf::*;
#[overload]
trait Xdd<T: Sized>: Sized {
    type J: Into<i32>;
    fn new(input: i32) -> T where T: Debug;
    // trait function with default implementation
    fn new(input: u32) -> String {
        "please use new(input1, input2) instead".to_string()
    }
    fn new<I: Into<u32>>(input1: I, input2: Self::J) -> T where T: Debug;
}
#[derive(Debug)]
struct Haha {
    a: u32,
    b: i32,
}
#[overload]
impl Xdd<Haha> for Haha {
    type J = i32;
    fn new(b: i32) -> Haha {
        Self {
            a: 1,
            b,
        }
    }
    fn new<I: Into<u32>>(a: I, b: Self::J) -> Haha {
        Self {
            a: a.into(),
            b,
        }
    }
}
let haha = Haha::new(12_i32);
assert_eq!(haha.a, 1_u32);
assert_eq!(haha.b, 12_i32);
let haha = Haha::new(9_u32, 2_i32);
assert_eq!(haha.a, 9_u32);
assert_eq!(haha.b, 2_i32);
assert_eq!(Haha::new(3_u32), "please use new(input1, input2) instead".to_string());

非特性和实现

#![feature(fn_traits, unboxed_closures)]
use overloadf::*;
#[derive(Debug)]
pub struct Haha {
    a: u32,
    b: i32,
}
#[overload]
impl Haha {
    pub fn new(b: i32) -> Self {
        Self {
            a: 1,
            b,
        }
    }
    pub fn new(a: u32) -> Self {
        Self {
            a,
            b: 2,
        }
    }
    // self in function parameter will be converted to associated type
    // that means no more syntax sugar like haha.normal()
    pub fn normal(&self) -> String {
        format!("{:?}", self)
    }
    pub fn normal(&self, prefix: &str) -> String {
        format!("{} {:?}", prefix, self)
    }
    // function without overloading is not influenced
    pub fn display(&self) -> String {
        format!("{:?}", self)
    }
}
let haha = Haha::new(12_i32);
assert_eq!(haha.a, 1_u32);
assert_eq!(haha.b, 12_i32);
let haha = Haha::new(9_u32);
assert_eq!(haha.a, 9_u32);
assert_eq!(haha.b, 2_i32);
assert_eq!(Haha::normal(&haha), "Haha { a: 9, b: 2 }");
assert_eq!(Haha::normal(&haha, "abc"), "abc Haha { a: 9, b: 2 }");
assert_eq!(haha.display(), "Haha { a: 9, b: 2 }");

默认属性

在函数中(目前不支持特性和),现在您可以装饰参数的默认值。我们不直接支持 parameter = value 语法的原因是,在派生的 TokenStream 中,值将首先通过编译器进行语法检查。默认值语法将被视为编译错误,并禁止我们解析和生成有效的标记。

示例

#![feature(fn_traits, unboxed_closures)]
use overloadf::*;
#[overload]
fn xdd(#[default(= 5_i32)] a: i32, #[default(= 32_u64)] b: u64) -> u64 { b - (a as u64) }
assert_eq!(xdd(3_i32), 29_u64);
assert_eq!(xdd(4_i32, 4_u64), 0);
assert_eq!(xdd(), 27_u64);
// compile error: expect i32 found u64
// assert_eq!(xdd(6_u64), 1_u64);
#![feature(fn_traits, unboxed_closures)]
use overloadf::*;
#[overload]
fn xdd(#[default(= 5_i32)] a: i32, b: u8, #[default(= 32_u64)] c: u64) -> u64 { c + (b as u64) - (a as u64) }
assert_eq!(xdd(4_i32, 7_u8), 35_u64);
assert_eq!(xdd(3_u8), 30_u64);

许可证

许可协议

贡献

除非您明确说明,否则您提交的任何贡献,均按上述许可协议进行许可,无需附加条款或条件。

依赖关系

~305–760KB
~18K SLoC