Say I have a newtype that I want to be generic over f32
and f64
. To express this, I use num_traits::Float
, like so:
use num_traits::Float;
struct Foo<T: Float>(T);
I would like to implement Float
for Foo
also. Most obvious is num_derive::Float
, but that seems to fail for generics. The following does not compile due to a lacking generic parameter, suggesting to use Foo<T><T: Float>(T)
.
use num_traits::Float;
#[derive(num_derive::Float)]
struct Foo<T: Float>(T);
(I would post a playground link, but num-traits is not included.) Indeed, there is an open issue that appears to confirm that this is not possible in num-derive.
The very helpful derive-more crate does support derives for generic newtypes, though, and so I figured that if I can auto-derive all the common operators, then I can manually implement the rest of the num-specific traits without too much hassle, maybe using some delegation crate to cut down on boilerplate. The following compiles and seems to work:
use derive_more::{Add, AddAssign};
use num_traits::Float;
#[derive(Add, AddAssign)] // And so on for the remaining operators...
struct Foo<T: Float>(T);
As far as I understand, however, derive_more
only helps me with Foo + Foo
, but cannot derive Foo + &Foo
, &Foo + Foo
, or &Foo + &Foo
, though it's very possible I'm missing some functionality in derive-more?
A couple of crates exist to derive operators for the various combinations of owned and borrowed values, but none of them appear to work for generic newtypes. These include newtype_derive and impl_ops (apparently succeeded by auto_ops).
My question, therefore, is how best to solve this problem? I'd rather avoid writing a tremendous amount of error-prone boilerplate for all the operations. I'm thinking I could probably solve this with macro_rules
, but I'm unfamiliar enough with macros for this to feel somewhat daunting, and I feels like a common enough problem that someone else must've come up with a good solution?