Reputation: 48058
Given a trait, we may want to implement it for many types.
pub trait RTypeUnit {
fn zero() -> Self;
fn one() -> Self;
}
impl RTypeUnit for usize { fn zero() -> usize { 0 } fn one() -> usize { 1 } }
impl RTypeUnit for isize { fn zero() -> isize { 0 } fn one() -> isize { 1 } }
impl RTypeUnit for u64 { fn zero() -> u64 { 0 } fn one() -> u64 { 1 } }
impl RTypeUnit for i64 { fn zero() -> i64 { 0 } fn one() -> i64 { 1 } }
impl RTypeUnit for u32 { fn zero() -> u32 { 0 } fn one() -> u32 { 1 } }
impl RTypeUnit for i32 { fn zero() -> i32 { 0 } fn one() -> i32 { 1 } }
impl RTypeUnit for u16 { fn zero() -> u16 { 0 } fn one() -> u16 { 1 } }
impl RTypeUnit for i16 { fn zero() -> i16 { 0 } fn one() -> i16 { 1 } }
impl RTypeUnit for u8 { fn zero() -> u8 { 0 } fn one() -> u8 { 1 } }
impl RTypeUnit for i8 { fn zero() -> i8 { 0 } fn one() -> i8 { 1 } }
What's an idiomatic way to avoid writing out functions for each type? Should I use default implementations, or maybe macros?
I am aware of the num
crate for these specific methods, but I'm interested to know how to do this in the general case.
Upvotes: 3
Views: 132
Reputation: 22203
As per Rust reference:
An implementation is an item that implements a trait for a specific type.
Take a look at the implementations of Zero
and One
in the docs (deprecated since Rust 1.11, I removed the deprecation attributes for brevity):
pub trait Zero: Sized {
fn zero() -> Self;
}
pub trait One: Sized {
fn one() -> Self;
}
macro_rules! zero_one_impl {
($($t:ty)*) => ($(
impl Zero for $t {
#[inline]
fn zero() -> Self { 0 }
}
impl One for $t {
#[inline]
fn one() -> Self { 1 }
}
)*)
}
zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
If the standard docs did it with macros, I doubt a better way exists.
Upvotes: 8