RFC: Add Quantity::as_ and Quantity::cast for changing the underlying storage type.#294
RFC: Add Quantity::as_ and Quantity::cast for changing the underlying storage type.#294adamreichold wants to merge 1 commit intoiliekturtles:masterfrom
Conversation
774ac46 to
04e0f60
Compare
I think we could add a separate trait trait ChangeStorage<Ul, Ur>: Units<Ul> {
type Units: Unit<Ur>;
}
impl<Ul, Ur> ChangeStorage<Ul, Ur> for $units<Ul> {
type Units = $units<Ur>;
}but I am not sure how much this would add w.r.t. generality as it would still cover only the |
|
Thanks for the PR! I'll take a look this coming week and see if I can figure out anything with the traits. |
|
I don't think using The following diff compiles so it works... right? I went a slightly different way and defined a I'll do some thinking about usability over the weekend as I think the ability to do type conversions is proven, it's just a matter of determining what the interface should be. diff --git a/src/lib.rs b/src/lib.rs
index be430b4..32b73cf 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -280,6 +280,10 @@ pub mod num {
#[cfg(feature = "bigint-support")]
pub use num_rational::BigRational;
+ pub mod cast {
+ pub use num_traits::cast::*;
+ }
+
#[cfg(any(feature = "rational-support", feature = "bigint-support"))]
pub mod rational {
pub use num_rational::*;
diff --git a/src/system.rs b/src/system.rs
index 6324553..e9aac7c 100644
--- a/src/system.rs
+++ b/src/system.rs
@@ -590,6 +590,34 @@ macro_rules! system {
impl_ops!(Sub, sub, -, SubAssign, sub_assign, -=, Diff,
Div, div, /, DivAssign, div_assign, /=, sub_div);
+ trait QuantityCast<D, U, V>: Sized
+ where
+ D: Dimension + ?Sized,
+ U: Units<V> + ?Sized,
+ V: $crate::num::Num + $crate::num::cast::ToPrimitive + $crate::Conversion<V>,
+ {
+ fn from(q: Quantity<D, U, V>) -> Option<Self>;
+ }
+
+ impl<D, Ur, Ul, Vr, Vl> QuantityCast<D, Ul, Vl> for Quantity<D, Ur, Vr>
+ where
+ D: Dimension + ?Sized,
+ Ur: Units<Vr> + ?Sized,
+ Ul: Units<Vl> + Units<Vr> + ?Sized,
+ Vr: $crate::num::Num + $crate::num::cast::NumCast + $crate::Conversion<Vr>,
+ Vl: $crate::num::Num + $crate::num::cast::ToPrimitive + $crate::Conversion<Vl>,
+ {
+ fn from(q: Quantity<D, Ul, Vl>) -> Option<Self>
+ {
+ <Vr as $crate::num::cast::NumCast>::from(q.value)
+ .map(|v| Quantity {
+ dimension: $crate::lib::marker::PhantomData,
+ units: $crate::lib::marker::PhantomData,
+ value: change_base::<D, Ul, Ur, Vr>(&v),
+ })
+ }
+ }
+
impl<D, U, V> Quantity<D, U, V>
where
D: Dimension + ?Sized, |
|
The trait bound which did not work out for me was Ul: Units<Vl> + Units<Vr> + ?Sized,as e.g. |
04e0f60 to
857de2b
Compare
|
consider impl https://github.com/kas-gui/easy-cast traits may be |
|
casts are good, for example #529 i would like casts because inputs are 64 bit, but I lift system to 128 bit as needed for aggregations |
A first go at something helping with #293.
The restriction to
$units<V>instead ofU: Units<V>seems a bit weird, but it was the only way I saw to enforce that the same set of base units would be used for the conversion. (The more general version fails with trait bound errors as e.g. thef32base units do not implementUnits<i32>and without generic associated types there is no way to ask aUnits<V>implementor for its equivalentUnits<W>implementor AFAIU.)Finally, while I added minimal doc tests, I am not sure where actual unit tests should end up as this involves at least two storage types by definition.