Implementing a trait for multiple types at once
Solution 1:
The only way to implement a trait once for many concrete types is to implement a trait for all types already implementing another trait.
For example, you can implement a marker trait Xed
and then:
impl<T> Double for T
where
T: Xed,
{
fn double(&self) {
/* ... */
}
}
However, Rust has principled generics. The only thing that you know about T
in the previous implementation is that T
implements the Xed
trait
, and therefore the only associated types/functions you can use are those coming from Xed
.
A trait cannot expose a field/attribute, only associated types, constants and functions, so Xed
would need a getter for x
(which need not be called x
).
If you wish to rely on syntactic (and not semantic) properties of the code, then use macros.
Solution 2:
Creating a macro also solves your problem:
struct A {
x: u32,
}
struct B {
x: u32,
}
trait T {
fn double(&self) -> u32;
}
macro_rules! impl_T {
(for $($t:ty),+) => {
$(impl T for $t {
fn double(&self) -> u32 {
self.x * 2
}
})*
}
}
impl_T!(for A, B);
fn main() {}
Solution 3:
Using the duplicate
attribute macro you can do the following:
use duplicate::duplicate;
#[duplicate(name; [A]; [B])]
impl T for name {
fn double(&self) -> u32 {
self.x * 2
}
}
This will expand to two identical implementations for the two structs. I know you said you didn't want to use macros, but I interpret that as meaning you don't want to roll your own macro, so I think this is a good compromise.
You could also use duplicate
to avoid repeating your struct definitions:
use duplicate::duplicate;
#[duplicate(name; [A]; [B])]
struct name {
x: u32,
}
Or go all-out if you for some reason need two identical structs with identical implements (at this point we should begin questioning why we need 2 structs at all :D):
use duplicate::duplicate;
#[duplicate(
mod_name struct_name;
[a] [A];
[b] [B];
)]
mod mod_name {
pub struct name {
x: u32,
}
impl T for name {
fn double(&self) -> u32 {
self.x * 2
}
}
}
mod a;
mod b;
pub use self::{a::*, b::*};