Наивный подход состоит в том, чтобы предположить, что все числа относятся к одному и тому же типу:
fn e3(n1: f32, n2: f32, n3: f32) -> f32 {
match (n1 <= n2, n1 <= n3, n2 <= n1, n2 <= n3) {
(true, true, _, _) => n2 * n2 + n3 * n3,
(_, _, true, true) => n1 * n1 + n3 * n3,
_ => n1 * n1 + n2 * n2,
}
}
Однако это не будет работать с несколькими типами (например, i32
, f32
или * 1006). *).
Для реализации обобщенной функции c я добавил следующие ограничения типа:
fn g_e3<T, U, V, R>(n1: T, n2: U, n3: V) -> R
where
T: std::cmp::PartialOrd + std::ops::Mul + std::convert::From<U> + std::convert::From<V>,
U: std::cmp::PartialOrd + std::ops::Mul + std::convert::From<T> + std::convert::From<V>,
V: std::cmp::PartialOrd + std::ops::Mul + std::convert::From<T> + std::convert::From<U>,
<T as std::ops::Mul>::Output: std::ops::Add,
<U as std::ops::Mul>::Output: std::ops::Add,
{
match (
n1 <= n2.into(),
n1 <= n3.into(),
n2 <= n1.into(),
n2 <= n3.into(),
) {
(true, true, _, _) => n2 * n2 + n3 * n3,
(_, _, true, true) => n1 * n1 + n3 * n3,
_ => n1 * n1 + n2 * n2,
}
}
Однако, чтобы описать тип результата R
Мне нужно добавить R: <<U as std::ops::Mul>::Output as std::ops::Add>::Output
, что недопустимо .
Чтобы обойти жесткость типов, я попытался определить макрос:
macro_rules! ge3 {
($n1:expr, $n2:expr, $n3:expr) => {
{
match ($n1 <= $n2.into(), $n1 <= $n3.into(), $n2 <= $n1.into(), $n2 <= $n3.into()) {
(true, true, _, _) => $n2 * $n2 + ($n3 * $n3).into(),
(_, _, true, true) => $n1 * $n1 + ($n3 * $n3).into(),
_ => $n1 * $n1 + ($n2 * $n2).into(),
}
}
};
}
Однако в Rust существует понятие тривиального (as
) и нетривиального приведения (into
). , Примитивное приведение не будет работать с into
, вам нужно использовать as
. Однако я не могу найти способ найти type
определенного expr
в макросе.