Reputation: 2039
Regular float literals do not work:
extern crate num_traits;
use num_traits::float::Float;
fn scale_float<T: Float>(x: T) -> T {
x * 0.54
}
fn main() {
let a: f64 = scale_float(1.23);
}
error[E0308]: mismatched types
--> src/main.rs:6:9
|
6 | x * 0.54
| ^^^^ expected type parameter, found floating-point variable
|
= note: expected type `T`
found type `{float}`
Upvotes: 11
Views: 3979
Reputation: 83
These days the numeric_literals
crate and its replace_float_literals
feature can be helpful in doing the necessary substitutions on a complex piece of code.
Upvotes: 1
Reputation: 430801
In certain cases, you can add a restriction that the generic type must be able to be multiplied by the type of the literal. Here, we allow any type that can be multiplied by a f64
so long as it produces the output type of T
via the trait bound Mul<f64, Output = T>
:
use num_traits::float::Float; // 0.2.6
use std::ops::Mul;
fn scale_float<T>(x: T) -> T
where
T: Float + Mul<f64, Output = T>,
{
x * 0.54
}
fn main() {
let a: f64 = scale_float(1.23);
}
This may not work directly for the original problem, but it might depending on what concrete types you need to work with.
Upvotes: 3
Reputation: 430801
Use the FromPrimitive
trait:
use num_traits::{cast::FromPrimitive, float::Float};
fn scale_float<T: Float + FromPrimitive>(x: T) -> T {
x * T::from_f64(0.54).unwrap()
}
Or the standard library From
/ Into
traits
fn scale_float<T>(x: T) -> T
where
T: Float,
f64: Into<T>
{
x * 0.54.into()
}
See also:
Upvotes: 15
Reputation: 30021
You can't create a Float
from a literal directly. I suggest an approach similar to the FloatConst
trait:
trait SomeDomainSpecificScaleFactor {
fn factor() -> Self;
}
impl SomeDomainSpecificScaleFactor for f32 {
fn factor() -> Self {
0.54
}
}
impl SomeDomainSpecificScaleFactor for f64 {
fn factor() -> Self {
0.54
}
}
fn scale_float<T: Float + SomeDomainSpecificScaleFactor>(x: T) -> T {
x * T::factor()
}
Upvotes: 1