#operator-overloading #operator #overloading #macro #op #impl

no-std gen_ops

Macros for operator overloading for generic types

7 unstable releases (3 breaking)

0.4.0 Jun 17, 2023
0.3.0 Apr 20, 2023
0.2.0 Sep 3, 2022
0.1.3 Aug 14, 2022
0.1.1 May 30, 2022

#473 in Rust patterns

Download history 628/week @ 2024-07-03 580/week @ 2024-07-10 889/week @ 2024-07-17 927/week @ 2024-07-24 2270/week @ 2024-07-31 2937/week @ 2024-08-07 3609/week @ 2024-08-14 3485/week @ 2024-08-21 4246/week @ 2024-08-28 5008/week @ 2024-09-04 2961/week @ 2024-09-11 4254/week @ 2024-09-18 9810/week @ 2024-09-25 12978/week @ 2024-10-02 11555/week @ 2024-10-09 14312/week @ 2024-10-16

49,676 downloads per month
Used in 18 crates (via range-set-blaze)

MIT license

52KB
1K SLoC

gen_ops

Rust macros for operator overloading of generic types.

build docs crate license

Usage

The macros need four statements

  1. (Optional) Generic parameter names
  2. Type signature or extended type signature
  3. Callable expressions for each operator, and optionally, where clause for each operator
  4. (Optional) Where clause for generic parameters

Note All statements end with a semicolon except the where clause.

Example

#[derive(Debug, Copy, Clone, PartialEq)]
struct Pair<T>(pub T, pub T);

#[inline]
fn sub_pair<T>(a: &Pair<T>, b: &Pair<T>) -> Pair<T>
where T: Sub<Output=T> + Copy {
    Pair(a.0 - b.0, a.1 - b.1)
}

gen_ops!(
    <T>;                               // Generic parameter names
    types Pair<T>, Pair<T> => Pair<T>; // Type signature

    //add doc strings like below

    /// Add two pairs
    /// 
    /// Returns `Pair`
    for + call |a: &Pair<T>, b: &Pair<T>| {
        Pair(a.0 + b.0, a.1 + b.1)
    };                // Callable expressions for operators
    (where T: Add<Output=T>)

    for - call sub_pair;  // Or use an existing function
    (where T: Sub<Output=T>) //where clause for - operator only

    where T: Copy //Where clause for all impls
);

let a = Pair(2, 3);
let b = Pair(1, 8);

println!("a + b = {:?}", a + b); //a + b = Pair(3, 11)
println!("a - b = {:?}", a - b); //a - b = Pair(1, -5)

gen_ops!

The primary macro for all operators.

#[derive(Debug, Copy, Clone, PartialEq)]
struct Pair<T>(pub T, pub T);

gen_ops!(
    <T>;
    types Pair<T>, Pair<T> => Pair<T>;
    for + call |a: &Pair<T>, b: &Pair<T>| Pair(a.0 + b.0, a.1 + b.1);
    (where T: Add<Output=T>)

    for - call |a: &Pair<T>, b: &Pair<T>| Pair(a.0 - b.0, a.1 - b.1);
    (where T: Sub<Output=T>)

    where T: Copy
);

let a = Pair(10, 5);
let b = Pair(8, 9);

println!("a + b = {:?}", a + b); // a + b = Pair(18, 14)
println!("a - b = {:?}", a - b); // a - b = Pair(2, -4)

gen_ops_comm!

Implements commutative operations.

#[derive(Debug, Copy, Clone, PartialEq)]
struct Pair<T>(pub T, pub T);

gen_ops_comm!(
    <T>;
    types Pair<T>, i32 => Pair<T>;
    for * call |a: &Pair<T>, b:&i32| Pair(a.0 * *b, a.1 * *b);
    (where T: Mul<i32, Output=T>)

    for & call |a: &Pair<T>, b:&i32| Pair(a.0 & *b, a.1 & *b);
    (where T: BitAnd<i32, Output=T>)

    where T: Copy
);
let a = Pair(12, 3);

println!("a * 5 = {:?}", a * 5); //a * 5 = Pair(60, 15)
println!("5 * a = {:?}", 5 * a); //5 * a = Pair(60, 15)
println!("a & 2 = {:?}", a & 2); //a & 2 = Pair(0, 2)
println!("2 & a = {:?}", 2 & a); //2 & a = Pair(0, 2)

gen_ops_ex!

Implements trait for borrowed types.

#[derive(Debug, Copy, Clone, PartialEq)]
struct Pair<T>(pub T, pub T);

gen_ops_ex!(
    <T>;
    types mut Pair<T>, T => Pair<T>;
    for * call |a: &Pair<T>, b:&T| Pair(a.0 * *b, a.1 * *b);
    where T: Mul<Output=T> + Copy
);

let mut a = Pair(12, 3);
{
    let mut b = &mut a;
    println!("&mut a * 2 = {:?}", b * 2);// &mut a * 2 = Pair(24, 6)
}
println!("&a * 2 = {:?}", &a * 2);// &a * 2 = Pair(24, 6)
println!("a * 2 = {:?}", a * 2);// a * 2 = Pair(24, 6)

gen_ops_comm_ex!

Implements commutative operations for borrowed types.

#[derive(Debug, Copy, Clone, PartialEq)]
struct Pair<T>(pub T, pub T);

gen_ops_comm_ex!(
    <T>;
    types ref Pair<T>, i32 => Pair<T>;
    for * call |a: &Pair<T>, b:&i32| Pair(a.0 * *b, a.1 * *b);
    where T: Mul<i32, Output=T> + Copy
);

let a = Pair(12, 3);
println!("a * 5 = {:?}", a * 5); //a * 5 = Pair(60, 15)
println!("5 * a = {:?}", 5 * a); //5 * a = Pair(60, 15)
println!("5 * &a = {:?}", 5 * &a); //5 * &a = Pair(60, 15)
println!("&a * 5 = {:?}", &a * 5); //&a * 5 = Pair(60, 15)

Docs

For more details see docs.

Inspiration

This project is inspired by auto_ops

No runtime deps