9个版本
0.1.8 | 2023年5月12日 |
---|---|
0.1.7 | 2020年5月29日 |
#2 在 #overload
54 每月下载量
24KB
146 代码行数(不含注释)
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);
许可证
许可协议
- MIT 许可证 (LICENSE-MIT 或 https://opensource.org/licences/MIT)
贡献
除非您明确说明,否则您提交的任何贡献,均按上述许可协议进行许可,无需附加条款或条件。
依赖关系
~305–760KB
~18K SLoC